46 lines
1.1 KiB
Haskell
Executable File
46 lines
1.1 KiB
Haskell
Executable File
#!/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)
|