Life Goes On

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

14問目

http://projecteuler.net/index.php?section=problems&id=14
以下の式で定義される数列(コラッツ予想によれば必ず1で終わる)があったとき、数列の長さを最大にする百万未満のnを求める。
n → n/2 (nが偶数のとき)
n → 3n + 1 (nが奇数のとき)
数列の長さをリストに格納して、maximumとtakeWhileで最大となるnを求めています。
本当はmaximumByを使って簡単に書きたかった(コメントアウト部分)のですが、10倍くらい時間がかかってしまうので止めました。どうやら関数lenが何度も評価されてるみたいです。なぜだろう?

main = print $ euler014 999999

euler014 :: Integer -> Int
euler014 n = (+ 1) $ length $ takeWhile (< (maximum lens)) lens
    where lens = map len [1..n]

-- euler014 :: Integer -> Integer
-- euler014 n = maximumBy (comparing len) [1..n]

len :: Integer -> Integer
len 1 = 1
len n = len (seq' n) + 1

seq' :: Integer -> Integer
seq' n
    | (mod n 2 == 0) = div n 2
    | otherwise = 3 * n + 1