Project Euler 4

http://projecteuler.net/index.php?section=problems&id=4


回文数の判定は、各桁に分解してリストをひっくり返して数に戻して元通りになっているかどうかを調べる。各桁に分解するのは再帰で。
リストを数に戻すには次のようにする。


numerize a = foldr (\x y -> x + y * 10) 0 a

foldrはPythonのreduceに当たる。本当はfoldlがreduceに当たる。rとlは右結合、左結合を意味し、


foldl f 0 [1, 2, 3] -- f(3, f(2, f(1, 0)))
foldr f 0 [1, 2, 3] -- f(0, f(1, f(2, 3)))

となる。


\x y -> x + y * 10

がラムダになる。
3桁同士の積を生成するには内包表記で、


num_list = [ 100..999 ]
[ m * n | m <- num_list, n <- num_list ]

とする。
最大の数を得るにはやはりfoldrを使う。


foldr max 0 a

左結合でも同じ結果が得られるが、Haskellの場合は右結合のほうが速いらしい。実際に動かしてみるとこんなコードでもかなり違った。


list_digits 0 = []
list_digits n = mod n 10 : list_digits(div n 10)

numerize a = foldr (\x y -> x + y * 10) 0 a
is_palindromic n = n == numerize(reverse(list_digits n))
num_list = [ 100..999 ]
a = filter is_palindromic [ m * n | m <- num_list, n <- num_list ]
max_list a = foldr max 0 a
main = print(max_list a)

とても遅い。Pythonで同様に書いたものと比べて倍以上かかった。