N-Queens
published
last modified
7kb
Given an board what are the different ways you can place queens on that board such that they cannot attack each other.
Queens can move any number of squares vertically, horizontally or diagnoally
Here are some possible configurations for a board.
Thought Process
If you were to look at the valid configuration of the board, you would notice that every queen is in it's own row and column. So as a start we know once we place a queen in a row, we cannot place another one in that row. We could try the next row and see if we can place a queen somewhere in this row. It might not lead to a valid solution, but it might. If this is sounding like a backtracking problem, then you are right.
Backtracking
On a high level, a solution could look something like: place queen in row, try the next row and see if any of the positions in that row are a valid placement for the queen. What does it mean to be a valid placement?
Valid Placement
If we place queen in any position on the board then we know column is knocked out. For example below column is unusable since a queen could attack there. Similarily that row is also knocked out since we just placed the queen there.
What about the diaganols? Well they are slightly more tricky.
Diaganol
The way I like to play around with 2D matrices is to try see if any of the indexes at each position reveal any pattern. If we think about it there are two kinds of diaganols we are dealing with.
The trick here is, if we take the indexes at each position in the positive and negative diaganols and plot them, you would notice that at each move a constant calculation is being performed.
Trivially for the positive diaganol it is . For example the diaganol starting at moves to which both equal . You can check this property for the rest of the positions.
Similarily, on the negative, each value is given by . For example, at position we move to then finally , all of which equal zero.
Valid Placement Revisited
So this means that we can check a position on the board is valid by making sure that any queens currently on the board can't attack it by checking:
- A valid row (which we don't have to keep track of because once we place a queen we simply move on to the next row)
- The knocked out columns
- The knocked out positive and negative diaganols
Looks like we have an algorithm to work with here.
Algorithm
We can follow these steps:
- If we reach the end of the board (i.e no more queens to place) add this configuration to our result
- Otherwise, for each column in this row, check if we can place a queen there
- If so place the queen and try out all positions in the next row
- If we've tried all columns and we can't find a valid configuration, return and take the queen back and try any other positions in the previous step
To keep track of the positions that we cannot place a queen into, we can keep a set of already used columns, positive diaganols and negative diaganols.
Implementation
These are the possible solutions for a board:
Gotcha
Don't forget to copy each individual row (list) or perform a deep copy if you are keeping a results list. Copying a 2D array does not copy the objects in it. Otherwise you will keep seeing an empty board becuase everytime you backtrack you remove the solution from every board!
Thanks for reading and happy coding.
Contact
If you have any comments or thoughts you can reach me at any of the places below.