I remember my brother telling me about the 8 queens puzzle when I was around 18. The goal is to put 8 queens on a 8x8 board, with no queen being able to take another one. It means 2 queens cannot be on the same row, nor on the same column, nor on the same diagonal.

At that time I just had an HP48G calculator and I like playing with it to make small programs using the RPL. You can check the full programming manual. It was quite messy to even type the program on a small calculator with a small screen, and there was no debugging whatsoever. Still I somehow managed to write a working program. I let it run for I think 4 or 6 hours, and it found maybe 50 or 60 solutions out of 92. Now there’s definitely some symmetry in the solutions, so I could easily have found the remaining ones. My brother used XL to solve the puzzle and got all the results at once.

I remembered it lately and thought of trying it in Javascript. I like Javascript as you can just press F12 in your browser and off you go, you can start typing. I like Chrome as you can easily save snippets. Similar things probably exists in other browsers.

Here’s the solution I wrote in just under an hour, without too much distraction. Probably not the best way to do it, but it works. Here I simply console.log all the results. I could return an array of all the solutions, but it would require cloning the solutions to keep them, so an additional (small) function to make.


(function() {
    var BoardSize = 8;
    var NumberOfSolutions = 0;

    function createBoard() {
        var board = [];
        for(var i=0; i<BoardSize; i++) {
            var row = [];
            for(var j=0; j<BoardSize; j++) {
                row.push(false);
            }
            board.push(row);
        }
        return board;
    }

    function compute() {
        walk(createBoard(), 0);
    }

    function walk(currentPositions, row) {
        for(var column=0; column<BoardSize; column++) {
            if (checkPosition(currentPositions, row, column)) {
                currentPositions[row][column] = true;
                if (row + 1 < BoardSize) {
                    // Continue to the next row.
                    walk(currentPositions, row + 1);
                } else {
                    // We're on the last row, we found a solution.
                    // Display it and continue.
                    display(currentPositions);
                }

                // Resets the current solution as we've already tried everything afterwards.
                currentPositions[row][column] = false;
            }
        }
    }

    function checkPosition(currentPositions, row, column) {
        // Check line (by design it's useless)

        // Check column
        for(var i=0; i<row; i++) {
            if (currentPositions[i][column]) {
                return false;
            }
        }

        // Check diagonal
        for(var col=0; col<BoardSize; col++) {
            if (col !== column) {
                var diff = Math.abs(column - col);
                var rowMinus = row - diff;
                if (rowMinus >= 0 && currentPositions[rowMinus][col]) {
                    return false;
                }

                var rowPlus = row + diff;
                if (rowPlus < BoardSize && currentPositions[rowPlus][col]) {
                    return false;
                }
            }
        }

        return true;
    }

    function display(solution) {
        NumberOfSolutions++;
        console.log("SOLUTION " + NumberOfSolutions);

        for(var i=0; i<BoardSize; i++) {
            var line = "";
            for(var j=0; j<BoardSize; j++) {
                line += solution[i][j] ? " X " : " _ ";
            }
            console.log(line);
        }

        console.log("--------------------------------");
    }

    compute();
})();