packages feed

hat-2.7.0.1: examples/Queens.hs

-- The queens problem made famous by Wirth.

type Board = [Int]

main :: IO ()
main =
  if null solutions then putStrLn "no solution!"
  else putStr (showBoard (head solutions))
  where
  solutions = queens 4

queens :: Int -> [Board]
queens n = valid n n 

valid :: Int -> Int -> [Board]
valid 0 n = [[]]
valid m n = filter safe (extend n (valid (m-1) n)) 

extend :: Int -> [Board] -> [Board]
extend n bs = consEach [1..n] bs 

consEach :: [a] -> [[a]] -> [[a]]
consEach [] y = []
consEach (a:x) y = map (a:) y ++ consEach x y 

safe :: Board -> Bool
safe (a:b) = no_threat a b 1

no_threat :: Int -> Board -> Int -> Bool
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) 

showBoard :: Board -> String 
showBoard b =
  unlines (concat (zipWith rank [1..] b))
  where
  rank r qcol =
    map line ["o o o", " \\|/ ", " === "]
    where
    line crown_slice =
      concat (zipWith square [1..] b)
      where
      square scol _ =
        if scol == qcol then crown_slice
        else if scol `rem` (2::Int) == r `rem` (2::Int) then "....."
        else "     "