misc/haskell/exs/Move.hs

46 lines
1.1 KiB
Haskell
Raw Normal View History

2018-08-05 18:53:07 +02:00
#!/usr/bin/env nix-script
#!>haskell
{- Learn you a Haskell exercise -}
import Control.Monad
import Data.List
import Data.Function
type Pos = (Int, Int)
chessboard = liftM2 (,) [1..8] [1..8]
-- | Compose a monadic function with itself n times
compose :: Monad m => (a -> m a) -> Int -> a -> m a
compose n = foldr (<=<) return . flip replicate n
-- | Calculate every possible next move
moves :: Pos -> [Pos]
moves (x, y) = filter (`elem` chessboard)
[ (x+2, y-1), (x+2, y+1)
, (x-2, y-1), (x-2, y+1)
, (x+1, y-2), (x+1, y+2)
, (x-1, y-2), (x-1, y+2) ]
-- | Positions the knight can reach in `n` moves
reachIn :: Int -> Pos -> [Pos]
reachIn = compose moves
-- | Test for a path between `start` and `end` in `n` moves
canReachIn :: Int -> Pos -> Pos -> Bool
canReachIn n start end = end `elem` reachIn n start
-- | Pretty print for the chessboard
pprint = putStrLn . show' . groupBy (on (==) fst) where
show' = concatMap $ (++"\n") . intercalate " " . map show
main = do
let
reached = nub $ reachIn 1 (1,2)
unreached = chessboard \\ reached
print (length reached)
pprint (sort reached)
print (length unreached)
pprint (sort unreached)