Last active
August 7, 2018 23:22
-
-
Save raganwald/e8896be8f032ba80019fd6a20fc6bb7d to your computer and use it in GitHub Desktop.
The Eight Queens Problem
This file contains 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
// Computes the twelve "fundamental" solutions to the eight queens problem | |
// by filtering the results of the "half-inductive" algorithm. | |
// | |
// see http://raganwald.com/2018/08/03/eight-queens.html | |
// | |
// search space: 2,750 candidate positions | |
function testDiagonals (queens) { | |
const nesw = [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."]; | |
const nwse = [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."]; | |
if (queens.length < 2) return true; | |
for (const [i, j] of queens) { | |
if (nwse[i + j] !== '.' || nesw[i + 7 - j] !== '.') return false; | |
nwse[i + j] = 'x'; | |
nesw[i + 7 - j] = 'x'; | |
} | |
return true; | |
} | |
const without = (array, element) => | |
array.filter(x => x !== element); | |
function * inductive ( | |
queens = [], | |
candidateColumns = [0, 1, 2, 3, 4, 5, 6, 7] | |
) { | |
if (queens.length === 8) { | |
yield queens; | |
} else { | |
for (const chosenColumn of candidateColumns) { | |
const candidateQueens = queens.concat([[queens.length, chosenColumn]]); | |
const remainingColumns = without(candidateColumns, chosenColumn); | |
if (testDiagonals(candidateQueens)) { | |
yield * inductive(candidateQueens, remainingColumns); | |
} | |
} | |
} | |
} | |
const allColumns = [0, 1, 2, 3, 4, 5, 6, 7]; | |
function * halfInductive () { | |
for (const column of [0, 1, 2, 3]) { | |
const candidateQueens = [[0, column]]; | |
const remainingColumns = without(allColumns, column); | |
yield * inductive(candidateQueens, remainingColumns); | |
} | |
} | |
function verticalReflection (queens) { | |
return queens.map( | |
([row, col]) => [row, 7 - col] | |
); | |
} | |
const sortQueens = queens => | |
queens.reduce( | |
(acc, [row, col]) => (acc[row] = [row, col], acc), | |
[null, null, null, null, null, null, null, null] | |
); | |
const rotateRight = queens => | |
sortQueens( queens.map(([row, col]) => [col, 7 - row]) ); | |
const rotations = solution => { | |
const rotations = [null, null, null]; | |
let temp = rotateRight(solution); | |
rotations[0] = temp; | |
temp = rotateRight(temp); | |
rotations[1] = temp; | |
temp = rotateRight(temp); | |
rotations[2] = temp; | |
return rotations; | |
} | |
const indexQueens = queens => queens.map(([row, col]) => `${row},${col}`).join(' '); | |
function * fundamentals (solutions) { | |
const solutionsSoFar = new Set(); | |
for (const solution of solutions) { | |
const iSolution = indexQueens(solution); | |
if (solutionsSoFar.has(iSolution)) continue; | |
solutionsSoFar.add(iSolution); | |
const rSolutions = rotations(solution); | |
const irSolutions = rSolutions.map(indexQueens); | |
for (let irSolution of irSolutions) { | |
solutionsSoFar.add(irSolution); | |
} | |
const vSolution = verticalReflection(solution); | |
const rvSolutions = rotations(vSolution); | |
const irvSolutions = rvSolutions.map(indexQueens); | |
for (let irvSolution of irvSolutions) { | |
solutionsSoFar.add(irvSolution); | |
} | |
yield solution; | |
} | |
} | |
function * mapWith (mapFunction, iterable) { | |
for (const element of iterable) { | |
yield mapFunction(element); | |
} | |
} | |
function niceDiagramOf (queens) { | |
const board = [ | |
["⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️"], | |
["⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️"], | |
["⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️"], | |
["⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️"], | |
["⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️"], | |
["⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️"], | |
["⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️"], | |
["⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️", "⬛️", "⬜️"] | |
]; | |
for (const [row, col] of queens) { | |
board[7 - row][col] = "👸🏾"; | |
} | |
return board.map(row => row.join('')).join("\n"); | |
} | |
mapWith(niceDiagramOf, fundamentals(halfInductive())) |
This file contains 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
// Computes the all 92 solutions to the eight queens problem | |
// by computing half of the results of the inductive solution | |
// and then adding their vertical reflections. | |
// | |
// see http://raganwald.com/2018/08/03/eight-queens.html | |
// | |
// search space: 2,750 candidate positions | |
function testDiagonals (queens) { | |
const nesw = [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."]; | |
const nwse = [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."]; | |
if (queens.length < 2) return true; | |
for (const [i, j] of queens) { | |
if (nwse[i + j] !== '.' || nesw[i + 7 - j] !== '.') return false; | |
nwse[i + j] = 'x'; | |
nesw[i + 7 - j] = 'x'; | |
} | |
return true; | |
} | |
const without = (array, element) => | |
array.filter(x => x !== element); | |
function * inductive ( | |
queens = [], | |
candidateColumns = [0, 1, 2, 3, 4, 5, 6, 7] | |
) { | |
if (queens.length === 8) { | |
yield queens; | |
} else { | |
for (const chosenColumn of candidateColumns) { | |
const candidateQueens = queens.concat([[queens.length, chosenColumn]]); | |
const remainingColumns = without(candidateColumns, chosenColumn); | |
if (testDiagonals(candidateQueens)) { | |
yield * inductive(candidateQueens, remainingColumns); | |
} | |
} | |
} | |
} | |
const allColumns = [0, 1, 2, 3, 4, 5, 6, 7]; | |
function * halfInductive () { | |
for (const column of [0, 1, 2, 3]) { | |
const candidateQueens = [[0, column]]; | |
const remainingColumns = without(allColumns, column); | |
yield * inductive(candidateQueens, remainingColumns); | |
} | |
} | |
function verticalReflection (queens) { | |
return queens.map( | |
([row, col]) => [row, 7 - col] | |
); | |
} | |
function * flatMapWith (fn, iterable) { | |
for (const element of iterable) { | |
yield * fn(element); | |
} | |
} | |
const withReflections = flatMapWith( | |
queens => [queens, verticalReflection(queens)], halfInductive()); | |
Array.from(withReflections).length | |
//=> 92 |
This file contains 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
// Computes the all 92 solutions to the eight queens problem | |
// by testing partial solutions to the "rooks" algorithm | |
// as they are created, thus pruning subtrees when possible. | |
// | |
// see http://raganwald.com/2018/08/03/eight-queens.html | |
// | |
// search space: 5,508 candidate positions | |
function testDiagonals (queens) { | |
const nesw = [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."]; | |
const nwse = [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."]; | |
if (queens.length < 2) return true; | |
for (const [i, j] of queens) { | |
if (nwse[i + j] !== '.' || nesw[i + 7 - j] !== '.') return false; | |
nwse[i + j] = 'x'; | |
nesw[i + 7 - j] = 'x'; | |
} | |
return true; | |
} | |
const without = (array, element) => | |
array.filter(x => x !== element); | |
function * inductive ( | |
queens = [], | |
candidateColumns = [0, 1, 2, 3, 4, 5, 6, 7] | |
) { | |
if (queens.length === 8) { | |
yield queens; | |
} else { | |
for (const chosenColumn of candidateColumns) { | |
const candidateQueens = queens.concat([[queens.length, chosenColumn]]); | |
const remainingColumns = without(candidateColumns, chosenColumn); | |
if (testDiagonals(candidateQueens)) { | |
yield * inductive(candidateQueens, remainingColumns); | |
} | |
} | |
} | |
} | |
Array.from(inductive()).length | |
//=> 92 |
This file contains 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
// Computes the all 92 solutions to the eight queens problem | |
// by generating all of the solutions to the eight rooks | |
// problem using permutations, and then filtering them | |
// by testing for diagonal attacks. | |
// | |
// see http://raganwald.com/2018/08/03/eight-queens.html | |
// | |
// search space: 40,320 candidate positions | |
function diagramOf (queens) { | |
const board = [ | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."] | |
]; | |
for (const [i, j] of queens) { | |
board[i][j] = "Q"; | |
} | |
return board.map(row => row.join('')).join("\n"); | |
} | |
function test (queens) { | |
const board = [ | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."] | |
]; | |
for (const [i, j] of queens) { | |
if (board[i][j] != '.') { | |
// square is occupied or threatened | |
return false; | |
} | |
for (let k = 0; k <= 7; ++k) { | |
// fill row and column | |
board[i][k] = board[k][j] = "x"; | |
const vOffset = k-i; | |
const hDiagonal1 = j - vOffset; | |
const hDiagonal2 = j + vOffset; | |
// fill diagonals | |
if (hDiagonal1 >= 0 && hDiagonal1 <= 7) { | |
board[k][hDiagonal1] = "x"; | |
} | |
if (hDiagonal2 >= 0 && hDiagonal2 <= 7) { | |
board[k][hDiagonal2] = "x"; | |
} | |
board[i][j] = "Q"; | |
} | |
} | |
return true; | |
} | |
function * filterWith (predicateFunction, iterable) { | |
for (const element of iterable) { | |
if (predicateFunction(element)) { | |
yield element; | |
} | |
} | |
} | |
function first (iterable) { | |
const [value] = iterable; | |
return value; | |
} | |
function * mapWith (mapFunction, iterable) { | |
for (const element of iterable) { | |
yield mapFunction(element); | |
} | |
} | |
function * permutations (arr, prefix = []) { | |
if (arr.length === 1) { | |
yield prefix.concat(arr); | |
} else if (arr.length > 1) { | |
for (let i = 0; i < arr.length; ++i) { | |
const chosen = arr[i]; | |
const remainder = arr.slice(0, i).concat(arr.slice(i+1, arr.length)) | |
yield * permutations(remainder, prefix.concat([chosen])); | |
} | |
} | |
} | |
const solutionsToEightRooks = mapWith( | |
ii => ii.map((i, j) => [i, j]), | |
permutations([0, 1, 2, 3, 4, 5, 6, 7]) | |
); | |
const solutionsToEightQueens = filterWith(test, solutionsToEightRooks); | |
diagramOf(first(solutionsToEightQueens)) |
This file contains 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
// Computes the all 92 solutions to the eight queens problem | |
// by computing all of the ways eight queens can be arranged | |
// on the board using 64 choose 8, then filtering them | |
// for horizontal, vertical, and diagonal attacks. | |
// | |
// see http://raganwald.com/2018/08/03/eight-queens.html | |
// | |
// search space: 4,426,165,368 candidate positions | |
function diagramOf (queens) { | |
const board = [ | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."] | |
]; | |
for (const [i, j] of queens) { | |
board[i][j] = "Q"; | |
} | |
return board.map(row => row.join('')).join("\n"); | |
} | |
function test (queens) { | |
const board = [ | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."] | |
]; | |
for (const [i, j] of queens) { | |
if (board[i][j] != '.') { | |
// square is occupied or threatened | |
return false; | |
} | |
for (let k = 0; k <= 7; ++k) { | |
// fill row and column | |
board[i][k] = board[k][j] = "x"; | |
const vOffset = k-i; | |
const hDiagonal1 = j - vOffset; | |
const hDiagonal2 = j + vOffset; | |
// fill diagonals | |
if (hDiagonal1 >= 0 && hDiagonal1 <= 7) { | |
board[k][hDiagonal1] = "x"; | |
} | |
if (hDiagonal2 >= 0 && hDiagonal2 <= 7) { | |
board[k][hDiagonal2] = "x"; | |
} | |
board[i][j] = "Q"; | |
} | |
} | |
return true; | |
} | |
function * filterWith (predicateFunction, iterable) { | |
for (const element of iterable) { | |
if (predicateFunction(element)) { | |
yield element; | |
} | |
} | |
} | |
function first (iterable) { | |
const [value] = iterable; | |
return value; | |
} | |
function * mapWith (mapFunction, iterable) { | |
for (const element of iterable) { | |
yield mapFunction(element); | |
} | |
} | |
function * choose (n, k, offset = 0) { | |
if (k === 1) { | |
for (let i = 0; i <= (n - k); ++i) { | |
yield [i + offset]; | |
} | |
} else if (k > 1) { | |
for (let i = 0; i <= (n - k); ++i) { | |
const remaining = n - i - 1; | |
const otherChoices = choose(remaining, k - 1, i + offset + 1); | |
yield * mapWith(x => [i + offset].concat(x), otherChoices); | |
} | |
} | |
} | |
const numberToPosition = n => [Math.floor(n/8), n % 8]; | |
const numbersToPositions = queenNumbers => queenNumbers.map(numberToPosition); | |
const combinationCandidates = mapWith(numbersToPositions, choose(64, 8)); | |
const solutionsToEightQueens = filterWith(test, combinationCandidates); | |
diagramOf(first(solutionsToEightQueens)) |
This file contains 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
// Computes the all 92 solutions to the eight queens problem | |
// by computing all of the possible arrangements of eight | |
// chess squares (64^8), then filtering them | |
// for horizontal, vertical, and diagonal attacks. | |
// | |
// see http://raganwald.com/2018/08/03/eight-queens.html | |
// | |
// search space: 281,474,976,710,656 candidate positions | |
function diagramOf (queens) { | |
const board = [ | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."] | |
]; | |
for (const [i, j] of queens) { | |
board[i][j] = "Q"; | |
} | |
return board.map(row => row.join('')).join("\n"); | |
} | |
function * mostPessimumGenerator () { | |
for (let i0 = 0; i0 <= 7; ++i0) { | |
for (let j0 = 0; j0 <= 7; ++j0) { | |
for (let i1 = 0; i1 <= 7; ++i1) { | |
for (let j1 = 0; j1 <= 7; ++j1) { | |
for (let i2 = 0; i2 <= 7; ++i2) { | |
for (let j2 = 0; j2 <= 7; ++j2) { | |
for (let i3 = 0; i3 <= 7; ++i3) { | |
for (let j3 = 0; j3 <= 7; ++j3) { | |
for (let i4 = 0; i4 <= 7; ++i4) { | |
for (let j4 = 0; j4 <= 7; ++j4) { | |
for (let i5 = 0; i5 <= 7; ++i5) { | |
for (let j5 = 0; j5 <= 7; ++j5) { | |
for (let i6 = 0; i6 <= 7; ++i6) { | |
for (let j6 = 0; j6 <= 7; ++j6) { | |
for (let i7 = 0; i7 <= 7; ++i7) { | |
for (let j7 = 0; j7 <= 7; ++j7) { | |
const queens = [ | |
[i0, j0], | |
[i1, j1], | |
[i2, j2], | |
[i3, j3], | |
[i4, j4], | |
[i5, j5], | |
[i6, j6], | |
[i7, j7] | |
]; | |
yield queens; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
function test (queens) { | |
const board = [ | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."], | |
[".", ".", ".", ".", ".", ".", ".", "."] | |
]; | |
for (const [i, j] of queens) { | |
if (board[i][j] != '.') { | |
// square is occupied or threatened | |
return false; | |
} | |
for (let k = 0; k <= 7; ++k) { | |
// fill row and column | |
board[i][k] = board[k][j] = "x"; | |
const vOffset = k-i; | |
const hDiagonal1 = j - vOffset; | |
const hDiagonal2 = j + vOffset; | |
// fill diagonals | |
if (hDiagonal1 >= 0 && hDiagonal1 <= 7) { | |
board[k][hDiagonal1] = "x"; | |
} | |
if (hDiagonal2 >= 0 && hDiagonal2 <= 7) { | |
board[k][hDiagonal2] = "x"; | |
} | |
board[i][j] = "Q"; | |
} | |
} | |
return true; | |
} | |
function * filterWith (predicateFunction, iterable) { | |
for (const element of iterable) { | |
if (predicateFunction(element)) { | |
yield element; | |
} | |
} | |
} | |
function first (iterable) { | |
const [value] = iterable; | |
return value; | |
} | |
const solutionsToEightQueens = filterWith(test, mostPessimumGenerator()); | |
diagramOf(first(solutionsToEightQueens)) |
This file contains 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
const OCCUPATION_HELPER = Symbol("occupationHelper"); | |
class Board { | |
constructor () { | |
this.threats = [ | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0 | |
]; | |
this.queenIndices = []; | |
} | |
isValid (index) { | |
return index >= 0 && index <= 63; | |
} | |
isAvailable (index) { | |
return this.threats[index] === 0; | |
} | |
isEmpty () { | |
return this.queenIndices.length === 0; | |
} | |
isOccupiable (index) { | |
if (this.isEmpty()) { | |
return this.isValid(index); | |
} else { | |
return this.isValid(index) && index > this.lastQueen() && this.isAvailable(index); | |
} | |
} | |
numberOfQueens () { | |
return this.queenIndices.length | |
} | |
hasQueens () { | |
return this.numberOfQueens() > 0; | |
} | |
queens () { | |
return this.queenIndices.map(index => [Math.floor(index / 8), index % 8]); | |
} | |
lastQueen () { | |
if (this.queenIndices.length > 0) { | |
return this.queenIndices[this.queenIndices.length - 1]; | |
} | |
} | |
* availableIndices () { | |
for (let index = (this.isEmpty() ? 0 : this.lastQueen() + 1); index <= 63; ++index) { | |
if (this.isAvailable(index)) { | |
yield index; | |
} | |
} | |
} | |
[OCCUPATION_HELPER] (index, action) { | |
const [row, col] = [Math.floor(index / 8), index % 8]; | |
// the rest of the row | |
const endOfTheRow = row * 8 + 7; | |
for (let iThreatened = index + 1; iThreatened <= endOfTheRow; ++iThreatened) { | |
action(iThreatened); | |
} | |
// the rest of the column | |
const endOfTheColumn = 56 + col; | |
for (let iThreatened = index + 8; iThreatened <= endOfTheColumn; iThreatened += 8) { | |
action(iThreatened); | |
} | |
// diagonals to the left | |
const lengthOfLeftDiagonal = Math.min(col, 7 - row); | |
for (let i = 1; i <= lengthOfLeftDiagonal; ++i) { | |
const [rowThreatened, colThreatened] = [row + i, col - i]; | |
const iThreatened = rowThreatened * 8 + colThreatened; | |
action(iThreatened); | |
} | |
// diagonals to the right | |
const lengthOfRightDiagonal = Math.min(7 - col, 7 - row); | |
for (let i = 1; i <= lengthOfRightDiagonal; ++i) { | |
const [rowThreatened, colThreatened] = [row + i, col + i]; | |
const iThreatened = rowThreatened * 8 + colThreatened; | |
action(iThreatened); | |
} | |
return this; | |
} | |
occupy (index) { | |
const occupyAction = index => { | |
++this.threats[index]; | |
}; | |
if (this.isOccupiable(index)) { | |
this.queenIndices.push(index); | |
return this[OCCUPATION_HELPER](index, occupyAction); | |
} | |
} | |
unoccupy () { | |
const unoccupyAction = index => { | |
--this.threats[index]; | |
}; | |
if (this.hasQueens()) { | |
const index = this.queenIndices.pop(); | |
return this[OCCUPATION_HELPER](index, unoccupyAction); | |
} | |
} | |
} | |
function * inductive (board = new Board()) { | |
if (board.numberOfQueens() === 8) { | |
yield board.queens(); | |
} else { | |
for (const index of board.availableIndices()) { | |
board.occupy(index); | |
yield * inductive(board); | |
board.unoccupy(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment