-- The classic 8-queens problem made famous by Wirth.
-- This version Colin Runciman, March 2000.
main =
if null solutions then putStrLn "no solution!"
else putStr (board (head solutions))
where
solutions = queens 8
queens :: Int -> [[Int]]
queens n = valid n n
valid :: Int -> Int -> [[Int]]
valid 0 n = [[]]
valid m n = filter safe (extend n (valid (m-1) n))
extend n b = cp (fromTo 1 n) b
cp :: [a] -> [[a]] -> [[a]]
cp [] y = []
cp (a:x) y = map (a:) y ++ cp x y
safe (a:b) = no_threat a b 1
no_threat a [] m = True
no_threat a (b:y) m =
a /= b && a+m /= b && a-m /= b && no_threat a y (m+1)
board :: [Int] -> String
board b =
unlines (concat (zipWith rank (from 1) b))
where
rank r qcol =
map line ["o o o", " \\|/ ", " === "]
where
line crown_slice =
concat (zipWith square (from 1) b)
where
square scol _ =
if scol == qcol then crown_slice
else if (scol `rem` (2::Int)) == (r `rem` (2::Int)) then "....."
else " "
-- in place of ..
from :: Int -> [Int]
from n = n : from (n+1)
fromTo :: Int -> Int -> [Int]
fromTo m n = if m > n then [] else m : fromTo (m+1) n
|