23問目
http://projecteuler.net/index.php?section=problems&id=23
約数の和が元の数より大きいものを過剰数と呼ぶ。28123より大きい数は必ず二つの過剰数の和として表現できるが、二つの過剰数の和として表現できない全ての数の和を求める。
問題自体はそれほど難しくないのですが、これまでで最も実行時間がかかっています。(コンパイル済みのコードで数十秒)
何をどうしたら高速化できるんだろう?
→ここで教えていただき、改善しました。
この問題は何度も見直してますが、単純に速さを求めるなら、Euler problems/Problem 23 - HaskellWiki のようにArrayモジュールを使うのが正解だと思います。
import Data.List main = print $ euler023 28123 euler023 :: Int -> Int euler023 limit = sum $ filter (not . isSumOfAbundants) [1..limit] isSumOfAbundants :: Int -> Bool isSumOfAbundants n = any test $ takeWhile (<= div n 2) abundants where abundants = filter isAbundant [1..] test a = isAbundant (n - a) isAbundant :: Int -> Bool isAbundant n = n < (sum $ divisors n) divisors :: Int -> [Int] divisors n = nub $ [1] ++ halfDivisors ++ (map (div n) halfDivisors) where halfDivisors = filter ((== 0) . mod n) [2..root] root = truncate $ sqrt $ fromIntegral n