Skip to content

Instantly share code, notes, and snippets.

@lqt0223
Last active March 12, 2018 08:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lqt0223/da906df9047eba4b3f7a3fc5edd44293 to your computer and use it in GitHub Desktop.
Save lqt0223/da906df9047eba4b3f7a3fc5edd44293 to your computer and use it in GitHub Desktop.
28 n-queens puzzle - a declarative solution
function queen(n) {
// a array of numerical sequence from 0 to n - 1
var sequence = enumerateInterval(0, n - 1)
// returns the sub-solution for n-queen's problem while placing k(k < n) queens on the first k rows of the board
function queenRow(k) {
if (k == 0) {
return [[]]
} else {
var restQueens = queenRow(k - 1)
// just place the nth queen on any place of the new row to generate a bunch of new solutions
var solutions = combine(restQueens, sequence)
// and filter solutions that is safe
return filter((positions) => safe(positions), solutions)
}
}
return queenRow(n)
}
// a1 is an array of array, a2 is an array
// this function will append every element in a2 into every element(array) in a1 and flatten the result
// ex. combine([[0, 1], [2, 3]], [4, 5]) will return [ [ 0, 1, 4 ], [ 0, 1, 5 ], [ 2, 3, 4 ], [ 2, 3, 5 ] ]
function combine(a1, a2) {
return flatMap((x) => {
return map((y) => {
if (typeof x == 'object') {
var t = x.slice()
t.push(y)
return t
} else {
return [x, y]
}
}, a2)
}, a1)
}
// test if the positions of queens is not attacking each other
// because of recursion, we can assume that all but the last queen is safe.
// therefore we only check the last queen against other queens
function safe(positions) {
var pos = positions.slice()
var i = pos.pop()
return _safe(i, pos)
}
function _safe(x, positions) {
return !included(x, positions) && !diagonal(x, positions)
}
function included(x, arr) {
return arr.some(i => i == x)
}
function diagonal(x, arr) {
return arr.some((t, i) => x - arr.length == t - i || x + arr.length == t + i)
}
function enumerateInterval(low, high) {
var result = []
for (var i = low; i <= high; i++) {
result.push(i)
}
return result
}
function flatMap(proc, list) {
return flatten(map(proc, list))
}
function flatten(arr) {
return arr.reduce((a, b) => {
return a.concat(b)
}, [])
}
function map(proc, list) {
return list.map(proc)
}
function filter(proc, list) {
return list.filter(proc)
}
// test
var result = queen(8)
console.log(result)
console.log(result.length) // 92
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment