Project Euler 2

フィボナッチ数列を作らなければならない。Haskellではどのように作ればいいか検索していたら、次のようなものが出てきた。


fib = 1 : 1 : [ a + b | (a, b) <- zip fib (tail fib) ]
http://www.sampou.org/haskell/tutorial-j/functions.html

さっぱり意味がわからないが、一つずつ見ていこう。
まず、


main = print(1:2:[3])

で、リストを結合しているようだ(本当は違うらしい)。


*Main> main
[1,2,3]
*Main>

これはダメ。


main = print(1:2:3)

:演算子の右はリストでなければならないらしい。
次に、最初の右はPythonにもあるリストの内包形式。例えば、


a = [ n * n for n in range(1, 11) ]

に相当するコードは次のように書く。


a = [ n * n | n <- [1..10] ]

tailは、頭だけ除いたリストを表す。


main = print(tail a)


*Main> main
[4,9,16,25,36,49,64,81,100]
*Main>

だから、


fib = 1 : 1 : [ a + b | (a, b) <- zip fib (tail fib) ]

fibは[1,1,…]で、tail fibは[1,…]なので、a = 1, b = 1, a + b = 2になる。だから、fibは[1,1,2,…]、tail fibは[1,2,…]、と続いて、フィボナッチ数列を表すことになる。

Fn+2 = Fn+1 + Fn
F1 = F2 = 1

という数学に近い考え方ができる。


n = 4 * 10 ^ 6
fib = 1 : 1 : [ a + b | (a, b) <- zip fib (tail fib) ]
main = print(sum(filter (\n -> mod n 2 == 0) (takeWhile (<= n) fib)))