Recently at my office I had a discussion about algorithms and the N-Queens problem came up. I didn’t know about it, so I decided to check it out and then I felt like I wanted to write an implementation in Scala. This blog post documents all of this.
The Problem
The N-Queens problem has the following definition:
Given a positive number N, position this many queens on a chess board of size NxN in a way that no two queens can attack each other.
The Solution
I started thinking about the possible solution. Like almost any algorithmic challenge, the best way to do this is to write it on paper first. A few things became apparent:
- You can’t have 2 queens on the same row – there must be exactly 1 queen on each row.
- You can’t have 2 queens on the same column – there must be exactly 1 queen on each column.
- You can’t have 2 queens on the same diagonal – there must be exactly 1 queen on each diagonal.
Now things started getting some shape and ideas started coming into my head. A very simple solution directly comes to mind, which involves having N
nested loops. This doesn’t sound great and it would waste time on lots of unnecessary computations.
Another idea came to mind, where you generate all combinations of single queen per row and column and then check the diagonals. This can be done nicely using bit operations with N
bit numbers. For example:
If N=4
, then you will need to compute all the permutations of the numbers 1 (0001)
, 2 (0010)
, 4 (0100)
and 8 (1000)
. These are all powers of 2 – from 0
to N-1
. The number of permutations of those 4 numbers is 4!
, which is 1*2*3*4 = 24
. This is already a big improvement to the initial idea, which was proposing nested loops with 4*4*4*4 = 256
solutions.
Backtracking
This blog post will focus on another solution – backtracking. It is basically a recursive method where we position queens in each column one by one until they don’t threaten each other or it’s not possible to do so. If not, then we backtrack a step at a time until we’ve found a solution or we’ve exhausted all possible solutions. It is an interesting method, so I will show the code for it here.
First of all, here is the implementation of a method that checks if it is safe to position a queen at a given position. Just because we position our queens column by column, we only need to check the left side and the upper left and lower left diagonals:
After we have defined this method, we can actually implement our backtracking algorithm:
This really is the main method in our program. Below follows a full program that uses the above methods and prints a solution:
Below is a snippet of an example run of the program:
This calculation came back almost instantly.
Conclusion
Here I presented a backtracking solution to the N-Queens problem implemented in Scala. I also mentioned about another solution using binary numbers and permutations to generate possible solutions and check them. In a future post I will write an implementation of the binary solution and will compare both methods against each other.