「人材獲得作戦・4 試験問題ほか」を解こうとしている(続・未完)
昨日 (d:id:i_k_b:20100113:1263400645) の続き。
探索問題なんだ、ということで検索してかつて読んで感動したページ「Search using Haskell」を再発見。
これを参考に書き直したコードが以下:
import Data.List import Monad main = do cs <- getContents let input = lines cs let answer = solve $ (next.from) input putStrLn $ unlines $ head $ answer from input = (startOf input, input) startOf x = fst $ head $ filter ((=='S').snd) x' where x' = concatMap (\(y,cs) -> zip (zip [0..] (repeat y)) cs) (zip [0..] x) solve [] = fail "no route found" solve ((p,b):queue) | symbol == ' ' = solve (queue ++ (next.modify) (p,b)) | symbol == 'G' = return b `mplus` (solve queue) | otherwise = solve queue where symbol = b!!(snd p)!!(fst p) modify ((x,y),b) = ((x,y), putAt y (putAt x '$' (b!!y)) b) putAt n v vs = take n vs ++ v : drop (n+1) vs inner ((x,y),b) = x >= 0 && y >= 0 && x < length (head b) && y < length b next = (filter inner) . move move (p,b) = zip [up p, dn p, lt p, rt p] (repeat b) where up (x,y) = (x,y-1) dn (x,y) = (x,y+1) lt (x,y) = (x-1,y) rt (x,y) = (x+1,y)
MonadPlus を使ってリストにしたから、見つかったら即結果を出してくれる…はず。…あんまり関係ないのかなあ?
また結果をひとつだけ返せばいいのだから main 関数の最後のアクション putStrLn $ unlines $ head $ answer では、リストに対する head でなく Maybe に対する fromJust にすればよい、気がする。
既訪の場所に来たらこれを落とす処理は、入れた方がいいのかしらん?おぼろげにだけれど入れなくても大丈夫な気がしている。というのは、動ける場所を $ に書き換えているから訪問済みの場所には入れないはず、というおぼろげな根拠による。
結果…(涙)
スタックオーバーフローですと…?
$ time cat map | runghc solver.hs Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. real 56m45.980s user 55m20.357s sys 0m16.283s