Life Goes On

まあまあだけど楽しんでる方です

34問目

http://projecteuler.net/index.php?section=problems&id=34
各桁の数字の階乗の和が元の数と等しくなるような数を全て足し合わせる。
9の階乗は6桁なので、求める数は高々7桁だと分かります。(それ以上だと元の数の桁数が階乗の和の桁数より必ず大きくなる)
あとは全ての数を調べているのですが、よく考えたら階乗の和になる数は限られているので、それに絞って調べた方がいいですね。
ちょっと考えてみよう。

import Data.Char

main = print euler034

euler034 :: Integer
euler034 = sum $ filter factSum [10..(facts !! 9)*7]
    where factSum n = n == (sum $ map ((facts !!) . digitToInt) $ show n)

facts :: [Integer]
facts = 1 : scanl1 (*) [1..]

という訳で修正したのが↓。
断然速いです。

import Data.Char
import Data.List

main = print $ sum $ euler034

euler034 :: [Int]
euler034 = map (sum . map (facts !!)) $
    filter factSum $ concat [ perm n | n <- [2..7] ]
    where factSum xs =
       xs == (map digitToInt $ sort $ show $ sum $ map (facts !!) xs)

perm :: Int -> [[Int]]
perm 1 = [ [x] | x <- [0..9] ]
perm n = [ x:xs | xs <- perm (n-1), x <- takeWhile (<= head xs) [0..9] ]

facts :: [Int]
facts = 1 : scanl1 (*) [1..]