Skip to content

Instantly share code, notes, and snippets.

@robot-dreams
Last active December 29, 2016 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robot-dreams/4f4a42e0fba0a798d57623842c65fd88 to your computer and use it in GitHub Desktop.
Save robot-dreams/4f4a42e0fba0a798d57623842c65fd88 to your computer and use it in GitHub Desktop.
Generate safe placements of n queens on a chessboard with n rows and n columns
import Control.Monad (foldM)
-- All safe placements of n queens, on a board with n rows and n columns; a
-- placement is safe if no two queens are attacking each other
queens :: Int -> [[(Int, Int)]]
queens n =
foldM (extend n) [] [1..n]
-- All possible ways to extend, on a board with n rows, an existing safe
-- placement of queens by adding an additional queen in column j
extend :: Int -> [(Int, Int)] -> Int -> [[(Int, Int)]]
extend n qs j =
filter safe $ addCol n j qs
where safe (q:qs) = not $ any (attacking q) qs
-- All possible ways to add an additional queen, on a board with n rows, in
-- column j, to an existing placement of queens
addCol :: Int -> Int -> [(Int, Int)] -> [[(Int, Int)]]
addCol n j qs =
(:) <$> col n j <*> [qs]
where col n j = zip [1..n] (repeat j)
-- Whether two queens placed at coordinates (i, j) and (i', j') are attacking
-- each other, i.e. whether they share a row, column, or diagonal
attacking :: (Int, Int) -> (Int, Int) -> Bool
attacking (i, j) (i', j') =
sameRow || sameCol || sameDiag
where sameRow = i == i'
sameCol = j == j'
sameDiag = abs (i - i') == abs (j - j')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment