takafumi blog

日々の勉強メモ

【Haskell】 H本 13.6のチェスの演習問題

環境   ghc 7.8.3 CentOS7.0

「すごいHaskellたのしく学ぼう!」第13章 メモ

13.6のチェスの演習問題をやってみた。

import Control.Monad

type KnightPos = (Int, Int)  -- (横, 縦)

moveKnight :: KnightPos -> [KnightPos]
moveKnight (c,r) = do
    (c', r') <- [(c+2,r-1),(c+2,r+1),(c-2,r-1),(c-2,r+1)
                ,(c+1,r-2),(c+1,r+2),(c-1,r-2),(c-1,r+2)
                ]
    guard (c' `elem` [1..8] && r' `elem` [1..8])
    return (c', r')

in3 :: KnightPos -> [KnightPos]
in3 start = return start >>= moveKnight >>= moveKnight >>= moveKnight

canReachIn3 :: KnightPos -> KnightPos -> Bool
canReachIn3 start end = end `elem` in3 start

-- -----------------
-- ここまで本と同じ
-- -----------------

type KnightRoute = [KnightPos]

routeKnight :: KnightRoute -> [KnightRoute]
routeKnight rt = return rt >>= (\x -> moveKnight $ head x) >>= \next -> [next:rt]

routeIn3 :: KnightPos -> [KnightRoute]
routeIn3 pos = return [pos] >>= routeKnight >>= routeKnight >>= routeKnight

reachRouteIn3 :: KnightPos -> KnightPos -> [KnightRoute]
reachRouteIn3 start end = reverse $ filter (\x -> end == head x) $ routeIn3 start
ghci> reachRouteIn3 (1,1) (3,2)
[[(3,2),(1,1),(2,3),(1,1)],
 [(3,2),(4,4),(2,3),(1,1)],
 [(3,2),(2,4),(3,2),(1,1)],
 [(3,2),(4,4),(3,2),(1,1)],
 [(3,2),(1,3),(3,2),(1,1)],
 [(3,2),(1,1),(3,2),(1,1)],
 [(3,2),(5,3),(3,2),(1,1)],
 [(3,2),(5,1),(3,2),(1,1)]
]

ghci> reachRouteIn3 (1,1) (7,4)
[[(7,4),(5,3),(3,2),(1,1)]]

ghci> reachRouteIn3 (1,1) (8,8)
[]

takafumi-s.hatenablog.com