Life Goes On

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

43問目

http://projecteuler.net/index.php?section=problems&id=43
0から9の数字を1回ずつ使って作る数について1つ目の数字をd1、2つ目の数字をd2とするとき、d2d3d4が2で割り切れ、d3d4d5が3で割り切れ、d4d5d6が5で割り切れ、…、d8d9d10が17で割り切れるような数を全て求めて足し合わせる。
数を生成しながら上述の条件を満たすものだけ抽出していくのですが、高速化のため末尾の数字(10桁目)から生成し、まずd8d9d10が17で割り切れるものだけに絞り込み、それに対し7桁目の数字を付け加えて13で割り切れるものを抽出しています。

import Data.List

main = print euler043

euler043 :: Integer
euler043 = sum $ map (read . snd) $ perms !! 10

perms :: [[(String, String)]]
perms = iterate perm [("0123456789", "")]

perm :: [(String, String)] -> [(String, String)]
perm = concatMap (\ (src, dst) ->
    [(delete x src, x : dst) | x <- src, divisible (x : dst)])

divisible :: String -> Bool
divisible digit
    | (n < 3 || n > 9) = True
    | otherwise = mod (read $ take 3 digit) (p !! n) == 0
    where p = [1,1,1,17,13,11,7,5,3,2,1]
          n = length digit