我正在学习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
功能?
答案 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)