将整数分解为数字列表

时间:2016-11-03 12:48:57

标签: haskell digits

我正在学习Haskell,我正在解决problem 30 on project Euler

digits n = if n<10 then [n] else (digits (quot n 10)) ++ [(mod n 10)]
isP30 n = (sum $ map (^5) $ digits n) == n
sum $ filter isP30 [10^5..10^6-1]

是否有更可读的方式来实现digits功能?

3 个答案:

答案 0 :(得分:3)

怎么样:

digits n = fmap digitToInt $ show n

我忘了提到你需要先从digitToInt导入Data.Char,就像@ bheklilr的回答一样。

答案 1 :(得分:2)

使用@ BenjaminHodgson的建议,你可以写一个unfold作为

import Data.Tuple (swap)
import Data.List (unfoldr)

digits = unfoldr go
    where go 0 = Nothing
          go n = Just (swap $ n `divMod` 10)

但是,由于unfoldr的工作原理,您将在此处以相反的顺序获取数字。另一种解决方案是完全抛弃它并与

一起使用
import Data.Char (digitToInt)

digits = map digitToInt . show

我的时间发现它更快,并且在未经优化的GHCi会话中使用了大约25%的内存,它也没有反转数字的顺序。

答案 2 :(得分:1)

首先,使用警卫而不是if-then-else编写代码总是更具可读性。所有无关紧要的事情也让人分心。

低效追加结束功能的标准转换,例如

digits n | n < 10    = [n] 
         | otherwise = digits (quot n 10) ++ [mod n 10]

是引入一个额外的参数,其中调用旧的digits n ++ xs与调用新的go n xs相同:

digits n = go n []   -- digits_old n ++ [] == go n []
   where
   go n next | n < 10    = n : next
             | otherwise = go (quot n 10) (mod n 10 : next)