Life Goes On

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

83問目

http://projecteuler.net/index.php?section=problems&id=83
80 × 80 の行列を左上から右下まで、上下左右に移動しながら辿るとき、各点の値の合計の最小値を求める。
次に進むべき点が分からないので、これまで通った点の近傍を進むべき点の候補としてリストに保持し、そのうち合計値が最小になるところから選んで進んでいきます。

import Data.List

main = do
    s <- readFile "matrix.txt"
    print $ euler083 $ matrix s

matrix :: String -> [[Int]]
matrix = map (read . (\ s -> "[" ++ s ++ "]")) . lines

euler083 :: [[Int]] -> Int
euler083 val = fst $ head $ dropWhile ((/= (m, m)) . snd)
    $ map (head . fst) $ iterate search ([(val !! 0 !! 0, (0, 0))], [])
    where
    search (a : as, bs) = (sort $ as ++ arround a (map snd $ as ++ bs), a : bs)
    arround (i, (x0, y0)) zs = [ (i + (val !! x !! y), (x, y)) |
        (x, y) <- [(x0, y0-1), (x0, y0+1), (x0-1, y0), (x0+1, y0)] \\ zs,
        x >= 0, x <= m, y >= 0, y <= m ]
    m = length val - 1