-- | Solution to the N-Queens problem illustrating separation of concerns. -- https://en.wikipedia.org/wiki/Eight_queens_puzzle module NQueens where import Data.List (find, permutations) -- | A position on a chess board. type Pos = (Int,Int) -- | An assignment of each queen to a position on the board. type Solution = [Pos] -- | Generate candidate solutions. Each row and column is used only once, -- so no queen can attack horizontally or vertically. candidates :: Int -> [Solution] candidates n = map (zip [1..n]) (permutations [1..n]) -- | Can two queens at these positions attack each other diagonally? diagonal :: Pos -> Pos -> Bool diagonal (x1,y1) (x2,y2) = abs (x1-x2) == abs (y1-y2) -- | Is this a valid solution? In other words, can no two queens attack -- each other diagonally? solution :: Solution -> Bool solution [] = True solution (p:ps) = not (any (diagonal p) ps) && solution ps -- | Solve the N-Queens problem. solve :: Int -> Maybe Solution solve = find solution . candidates -- | Find all solutions to the N-Queens problem. solveAll :: Int -> [Solution] solveAll = filter solution . candidates