2

I'm new to recursion and backtracking. I am trying to complete the N-Queen problem to print all solutions instead of just 1 and to understand these concepts.

I think I have the algorithm implemented partially right as I get some of the solutions but not all printed. My code is in Java.

  • For a value of N = 4, I get 2 solutions - this is right
  • For a value of N = 5, I get 5 solutions - there are actually 10
  • For a values of N= 8, I get none printed

I cannot figure out what mistake I am making. The idea I have is to realize that the 1st queen has to go in the first row, 2nd in the second row etc.I have to figure out which column is appropriate obviously taking care of diagonals to place a queen.

Any help in pointing me in the right direction is appreciated. My code is below and I have tried to add comments so that it helps with understanding.

public class nQueens {

    static class Queen {
        public Queen( int row, int column) {
            this.row = row;
            this.column = column;
        }
        int row = -1;
        int column = -1;
    }

    static ArrayList<Queen> queens = new ArrayList<Queen>();

    public static void main(String argv[]) {
        int n = 5;
        int[][] chessBoard = new int[n][n];
        int placed = 0;
        solve(n, chessBoard, placed);
    }

    public static void solve(int n, int[][] chessBoard, int placed) {
        // this means that all the queens have been placed
        if (placed == n) {
            System.out.println("**** Solution *****");
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    System.out.print(chessBoard[i][j] + " ");
                }
                System.out.println();
            }
        } else {
            // we know that each queen can be placed on each row
            int i = placed;
            // iterate through the columns
            for (int j = 0; j < n; j++) {
                if (chessBoard[i][j] != 1) {
                    if (isSafe(i, j)) {
                        chessBoard[i][j] = 1;
                        Queen queen = new Queen( i, j);
                        queens.add(queen);
                        placed = placed + 1;
                        // solve for the remaining number of queens
                        solve(n, chessBoard, placed);
                        // un-mark the spot
                        chessBoard[i][j] = 0;
                        // remove the placed queen
                        queens.remove(queens.size() - 1);
                        placed = placed - 1;
                    }
                }
            }
        }
    }

    public static boolean isSafe(int row, int column) {
        // this means that there are no queens on the board
        if (queens.isEmpty()) {
            return true;
        } else {
            for (int i = 0; i < queens.size(); i++) {
                // same column
                if (queens.get(i).column == column) {
                    return false;
                }
                // check diagonal
                int slope = Math.abs((queens.get(i).row - row) / (queens.get(i).column - column));
                if (slope == 1) {
                    return false;
                }
            }
        }
        return true;
    }
}
Spindoctor
  • 434
  • 3
  • 17
  • 1
    If I understand your code correctly, you only set a queen on the board, i.e. you mark one field. But where do you mark the fields that new queen can reach, i.e. which are blocked for other queens? I.e. if you set the 1st queen at (1,1), then all fields in row (1,x), column (x,1) and diagonal (x,x) must be marked as "blocked". Then the recursion can't place the 2nd queen at (2, 1), (2, 2) but starting at (2, 3). To solve your issue you'll need to make a *clone* of the current chessboard layout and pass it into `solve(n+1)`. – Stefan Becker Feb 18 '19 at 21:12
  • 1
    But where do you mark the fields that new queen can reach, i.e. which are blocked for other queens? -- so how I overcome this is if I placed the 1st queen then I know the 2nd queen must go on the second row there fore the first row is blocked off. – Spindoctor Feb 18 '19 at 21:24
  • 2
    When you enter `solve()` and then the `else` branch, you (a) make a new chessboard, (b) on each loop iteration you copy the contents of the *passed in* chessboard to that new chessboard, (c) you call a function that places the new queen on the new chessboard (it needs to also fill the rows, columns & diagonals!), (d) you call `solve()` with the new chessboard. I.e. each recursion level has its **own** chessboard to work on and a **passed in** chessboard from the caller for initialization (i.e. it has the queens already placed on the board by the higher recursion levels). – Stefan Becker Feb 18 '19 at 21:28
  • 1
    ok let me digest what you are trying to say here. Thank you again. – Spindoctor Feb 18 '19 at 22:12
  • I started to wonder when I read your code again: why do you keep a chessboard at all for the algorithm you have chosen? (a) you do not mark what fields are blocked by queens in your chessboard, hence your conditional `chessBoard[i][j] != 1` will always return true and call `isSafe()`, (b) `isSafe()` just uses the list of queens, (c) your solution print uses the chessboard, but instead could just use the list of queens instead. As your code has to always call `isSafe()` to figure out if a position is "free" it is also less efficient than a solution that keeps the state in a chessboard. – Stefan Becker Feb 20 '19 at 06:05

2 Answers2

1

The problem is:

int slope = Math.abs((queens.get(i).row - row) / (queens.get(i).column - column));
if (slope == 1) {
    return false;
}

You're casting slope to an integer. This means that a slope of 1.5 or 1.3 becomes 1 and results in you returning false even though a queen isn't actually on that diagonal.

Instead cast to float before the division (note that java's division is integer division so you need to cast either the divisor or the dividend to a float first to get a float output) to allow for floating point slopes:

float tmp = (queens.get(i).row - row);
float slope = Math.abs(tmp/ (queens.get(i).column - column));
if (slope == 1) {
    return false;
}
Primusa
  • 13,136
  • 3
  • 33
  • 53
  • Thank you. I was busy looking at the algorithm when infact it was something so tiny yet so significant. Thanks. I have been looking at this for a while until that little change fixed it completely!!! – Spindoctor Feb 19 '19 at 12:11
1

An alternative solution to isSafe() and class Queen

  • make the chess board a class to track the status
  • recurse
    • clone the current board status
    • set the queen and block all fields reachable by her
    • pass the clone downwards for the next row
  • remember the column-per-row positions for each queen

The following is a generic solver which gets passed in a placer closure. By using the approach it is simple to use the same solver for rooks (placeRook()), knights (placeKnight()) or bishops (placeBishop()).

Please note that my solution is written in Groovy, which also runs on JVM, and is very close to Java. So it should be no problem to translate the juicy bits of the algorithm to Java.

class ChessBoard {
    int N
    int lastIndex
    private boolean[][] board
    int solutions

    ChessBoard(int n) {
        board     = new boolean[n][n]
        N         = n
        lastIndex = n - 1
        solutions = 0
        this.each { int row, int column -> board[row][column] = true }
    }

    ChessBoard(ChessBoard orig) {
        N         = orig.getN()
        board     = new boolean[N][N]
        lastIndex = N - 1
        solutions = 0
        this.each { int row, int column -> board[row][column] = orig.getField(row, column) }
    }

    void each(Closure c) {
        (0..lastIndex).each { row ->
            (0..lastIndex).each { column -> c(row, column) }
        }
    }

    void print() {
        println " ${'-' * N}"
        (0..lastIndex).each { row ->
            print "|"
            (0..lastIndex).each { column -> print "${board[row][column] ? ' ' : 'X'}" }
            println "|"
        }
        println " ${'-' * N}"
    }

    int getN()                            { return N }
    int getSolutions()                    { return solutions }
    boolean getField(int row, int column) { return board[row][column] }

    void blockField(int row, int column)  {
        if ((row < 0) || (row > lastIndex))
            return
        if ((column < 0) || (column > lastIndex))
            return
        board[row][column] = false
    }

    List<Integer> getFree(int row)            {
        (0..lastIndex).findResults { int column -> board[row][column] ? column : null }
    }

    void placeQueen(int row, int column, boolean all = true) {
        if (all) {
            (0..lastIndex).each { offset ->
                blockField(row,    offset)                // row
                blockField(offset, column)                // column
                blockField(row + offset, column + offset) // diagonals
                blockField(row + offset, column - offset)
                blockField(row - offset, column + offset)
                blockField(row - offset, column - offset)
            }
        } else {
            blockField(row, column)
        }
    }

    // recursive solver
    void solve(ChessBoard previous, List<Integer> columns, int row, Closure placer) {
        List<Integer> free = previous.getFree(row)
        if (row < lastIndex) {
            // recurse
            free.each { column ->
                ChessBoard work = new ChessBoard(previous)
                columns[row] = column
                placer(work, row, column, true)
                solve(work, columns, row + 1, placer)
            }
        } else {
            // solutions
            free.each { column ->
                ChessBoard solution = new ChessBoard(N)
                columns[row] = column
                (0..lastIndex).each { placer(solution, it, columns[it], false) }
                println "Solution #${++solutions}:"
                solution.print()
            }
        }
    }

    // start recursion
    void solve(Closure placer) {
        List<Integer> columns = []
        solve(this, columns, 0, placer)
    }
}

board = new ChessBoard(8)
board.solve { ChessBoard work, int row, int column, boolean all -> work.placeQueen(row, column, all) }
println "Solutions: ${board.getSolutions()}"

Test run:

Solution #1:
 --------
|X       |
|    X   |
|       X|
|     X  |
|  X     |
|      X |
| X      |
|   X    |
 --------
...
Solution #92:
 --------
|       X|
|   X    |
|X       |
|  X     |
|     X  |
| X      |
|      X |
|    X   |
 --------
Solutions: 92

If my memory serves me correctly, 92 does sound correct for the 8-Queen problem. But it has been over 35 years since I solved this in school using an iterative approach in Pascal :-)


UPDATE improved solution

  • split original class into ChessBoard for tracking state and Solver for the algorithm
  • placers for queens, rooks, bishops & knights
  • calculate solutions for sizes 1 to 8
  • generate markdown table for the results
class ChessBoard {
    private int         N
    private int         lastIndex
    private boolean[][] state

    ChessBoard(int n) {
        N         = n
        lastIndex = N - 1
        state     = new boolean[N][N]
        (0..lastIndex).each { row ->
            (0..lastIndex).each { column ->
                setField(row, column, true)
            }
        }
    }

    ChessBoard(ChessBoard orig) {
        N         = orig.getN()
        lastIndex = N - 1
        state     = new boolean[N][N]
        (0..lastIndex).each { row ->
            (0..lastIndex).each { column ->
                setField(row, column, orig.getField(row, column))
            }
        }
    }

    int getN() {
        return N
    }

    boolean getField(int row, int column) {
        return state[row][column]
    }

    void setField(int row, int column, boolean free = false)  {
        if ((row < 0) || (row > lastIndex))
            return
        if ((column < 0) || (column > lastIndex))
            return
        state[row][column] = free
    }

    List<Integer> getFree(int row) {
        (0..lastIndex)
            .findResults { int column ->
            getField(row, column) ? column : null
        }
    }

    // for debugging only
    void print() {
        println " ${'-' * N}"
        (0..lastIndex).each { row ->
            print "|"
            (0..lastIndex).each { column -> print "${getField(row, column) ? ' ' : 'X'}" }
            println "|"
        }
        println " ${'-' * N}"
    }
}

class Solver {
    private int   N
    private int   lastIndex
    private int   solutions
    private int[] columns

    Solver(int n) {
        N         = n
        lastIndex = N - 1
        solutions = 0
        columns   = new int[N]
    }

    void printSolution(String label) {
        solutions++
        if (!label)
            return
        println "${N}-${label} solution #${solutions}"
        println " ${'-' * N}"
        (0..lastIndex).each { row ->
            int column = columns[row]
            println "|${' ' * column}X${' ' * (lastIndex - column)}|"
        }
        println " ${'-' * N}"
    }

    int getSolutions() {
        return solutions
    }

    void placeQueen(ChessBoard board, int row, int column) {
            // only modify fields from (row+1) downwards
            (1..(lastIndex - row)).each { offset ->
                board.setField(row + offset, column)          // column
                board.setField(row + offset, column + offset) // diagonals
                board.setField(row + offset, column - offset)
            }
    }

    void placeRook(ChessBoard board, int row, int column) {
        // only modify fields from (row+1) downwards
        (1..(lastIndex - row)).each { offset ->
            board.setField(row + offset, column) // column
        }
    }

    void placeBishop(ChessBoard board, int row, int column) {
        // only modify fields from (row+1) downwards
        (1..(lastIndex - row)).each { offset ->
            board.setField(row + offset, column + offset) // diagonals
            board.setField(row + offset, column - offset)
        }
    }

    static void placeKnight(ChessBoard board, int row, int column) {
        // only modify fields from (row+1) downwards
        board.setField(row + 1, column - 2)
        board.setField(row + 1, column + 2)
        board.setField(row + 2, column - 1)
        board.setField(row + 2, column + 1)
    }

    // recursive solver
    void solve(ChessBoard previous, int row, Closure placer, String label) {
        List<Integer> free = previous.getFree(row)
        if (row < lastIndex) {
            // recurse
            free.each { column ->
                ChessBoard work = new ChessBoard(previous)
                columns[row] = column
                placer(this, work, row, column)
                solve(work, row + 1, placer, label)
            }
        } else {
            // solutions
            free.each { column ->
                columns[row] = column
                printSolution(label)
            }
        }
    }

    // start recursion
    int solve(Closure placer, String label = null) {
        solve(new ChessBoard(N), 0, placer, label)
        return solutions
    }
}

Map<String, Closure> placers = [
    'Queens':  { Solver solver, ChessBoard board, int row, int column -> solver.placeQueen(board,  row, column) },
    'Rooks':   { Solver solver, ChessBoard board, int row, int column -> solver.placeRook(board,   row, column) },
    'Bishops': { Solver solver, ChessBoard board, int row, int column -> solver.placeBishop(board, row, column) },
    'Knights': { Solver solver, ChessBoard board, int row, int column -> solver.placeKnight(board, row, column) },
]
Map<String, List<Integer>> solutions = [:]

// generate solutions up to maxN
int     maxN  = 8
boolean print = false
placers
    .keySet()
    .each { String key ->
        Closure placer = placers[key]
        List<Integer> results = []
        (1..maxN).each { N ->
            results.push(new Solver(N).solve(placer, print ? key : null))
        }
        solutions[key] = results
    }

// generate markdown table from solutions
List lines = []
    (0..maxN).each { lines[it] = [it ?: 'Size'] }
[
    'Queens',
    'Rooks',
    'Bishops',
    'Knights',
].each { key ->
    List<Integer> results = solutions[key]
    lines[0].push(key)
    (1..maxN).each { lines[it].push(results[it - 1]) }
}

lines.each { line -> println line.join('|') }
return

Result table:

| Size | Queens | Rooks | Bishops | Knights |
|------|--------|-------|---------|---------|
|   1  |      1 |     1 |       1 |       1 |
|   2  |      0 |     2 |       2 |       4 |
|   3  |      0 |     6 |       5 |       9 |
|   4  |      2 |    24 |      24 |      52 |
|   5  |     10 |   120 |     125 |     451 |
|   6  |      4 |   720 |     796 |    4898 |
|   7  |     40 |  5040 |    5635 |   67381 |
|   8  |     92 | 40320 |   48042 | 1131382 |
|------|--------|-------|---------|---------|
Stefan Becker
  • 5,695
  • 9
  • 20
  • 30