Last active
December 29, 2016 19:49
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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