About the eight queens problem of JavaScript solution, always feel that it is necessary to learn the algorithm, which day to use when the discovery is really not embarrassed

Background

The eight queen question is a chess-background question: How can you place eight queens on the 8x8 chess board so that no queen can eat the other queen directly? In order to do this, neither queen can be in the same horizontal, vertical or diagonal line.

The eight queens problem can be extended to the more general n Queens placement problem: the size of the chessboard becomes nxn, and the number of Queens becomes N. Problem has solution when and only if n = 1 or n≥4

The Blind enumeration algorithm

through the N-cycle, the enumeration satisfies the constraints of the solution (eight cyclic code a lot, here for the four cycles), find all the possible positions of four queens, and then the whole board to determine whether the four queens will directly eat each other, the process of thinking is relatively simple

function Check1 (arr, n) {for
(var i = 0; i < n; i++) {for
(var j = i + 1; j < N; j +) {
if (arr[i] = = AR R[J]) | | Math.Abs (Arr[i]-arr[j]) = = j-i) {return
false
;
}}} return true;
}
function Queen1 () {
var arr = [];
for (arr[0] = 1; arr[0] <= 4; arr[0]++) {for
(arr[1] = 1; arr[1] <= 4; arr[1]++) {for
(arr[2] = 1; arr[2] & Lt;= 4; arr[2]++) {
for (arr[3] = 1; arr[3] <= 4; arr[3]++) {
if (!check1 (arr, 4)) {
continue;
} else {
Console.log (arr)
;
}}}} Queen1 ();
[2, 4, 1, 3]
//[3, 1, 4, 2]

As for the result, in the 4*4 chessboard, four queens can not be in a row, arr[0] to arr[3] respectively corresponding to four queens, the array of subscript and subscript corresponding to the value of the Queen in the Board position

Backtracking method

"Not go through, on the back", in the appropriate node to judge whether the conformity, does not conform to no longer carry out this road of exploration

function Check2 (arr, n) {for
(var i = 0; I <= n-1; i++) {
if ((Math.Abs (arr[i)-arr[n]) = = N-i) | | (Arr[i] = = Arr[n]) {return
false;
}
}
return true;
}
function Queen2 () {
var arr = [];
for (arr[0] = 1; arr[0] <= 4; arr[0]++) {
for (arr[1] = 1; arr[1] <= 4; arr[1]++) {
if (!check2 (arr, 1)) cont Inue; Put two queens in conflict situations for
(arr[2] = 1; arr[2] <= 4; arr[2]++) {
if (!check2 (arr, 2)) continue;//(Three Queens) conflict situations
for (arr[3] = 1; arr[3] <= 4; arr[3]++) {
if (!check2 (arr, 3)) {
continue;
} else {
console.log (arr) ;
}
}
}
}
}
}
Queen2 ();
[2, 4, 1, 3]
//[3, 1, 4, 2]

Non-recursive backtracking method

Algorithm Framework:

while (k > 0 "There is a road to go" and "did not reach the target") {//k > 0 There is a path to go
if (k > N) {//Search to leaf node
//Search to a solution, output
} else {
//a[ K] the first possible value while
("a[k] is not satisfied with the constraint and in the search space") {
//a[k] The next possible value
}
if ("a[k] in the search space") {
//mark the resource occupied
/ /k = k + 1;
} else {
//clean up the state space
/k = k-1}
}}

The concrete code is as follows, the outermost while below consists of two parts, one is the traversal of the current queen's possible values, and the other is to decide whether to go to the next level or back

function backdate (n) {
var arr = [];
var k = 1; Queen Arr[0 of nth
] = 1;
while (k > 0) {
arr[k-1] = arr[k-1] + 1;
while ((Arr[k-1] <= N) && (!check2 (arr, k-1)) {
arr[k-1] = arr[k-1] + 1;
}
The Queen satisfies the constraint conditions and makes the next decision
if (Arr[k-1] <= N) {
if (k = = N) {//nth Queen
Console.log (arr);
} else {
K = k + 1; Next Queen
arr[k-1] = 0;
}
else {
k = k-1;//Backtracking, previous Queen}
}
backdate (4);
[2, 4, 1, 3]
//[3, 1, 4, 2]

Recursive backtracking method

recursive calls greatly reduce the amount of code, but also increase the readability of the program

var arr = [], n = 4;
function Backtrack (k) {
if (k > N) {
console.log (arr);
} else {for
(var i = 1;i <= n; i++) {arr[k-1] = i;
if (Check2 (arr, k-1)) {
Backtrack (k + 1);
}
}} Backtrack (1);
[2, 4, 1, 3]
//[3, 1, 4, 2]

Flashy Amb.

What is Amb? Give it a list of data that can return a way to satisfy a constraint's success, fail without success, and, of course, return all success. The author has written so many points above, is to recommend this AMB algorithm here, it is suitable for dealing with simple backtracking scenes, very interesting, let's see how it works

First of all, to deal with a small problem, look for adjacent strings: to get a few sets of string arrays, each array to take out a string, the previous string of the last character is the same as the first character of the last string, satisfies the condition to output the new set of strings

Ambrun (function (Amb, fail) {
//constraint method
function linked (S1, S2) {return
s1.slice ( -1) = = S2.slice (0, 1);
}
//Inject data list
var w1 = Amb (["The", "that", "a"]);
var w2 = Amb (["Frog", "Elephant", "thing"]);
var W3 = Amb (["Walked", "treaded", "grows"]);
var W4 = Amb (["Slowly", "quickly"]);
Executes the program
if (!) ( Linked (W1, W2) && linked (W2, W3) && linked (W3, W4)) fail ();
Console.log ([W1, W2, W3, W4].join (")");
"That thing grows Slowly"
});

It looks super neat. But the premise is that you don't care about performance, it's really a waste of time!

Here's the JavaScript implementation, and it's interesting to study how it pulls back backwards.

function Ambrun (func) {
var choices = [];
var index;
function Amb (values) {
if (values.length = 0) {
fail ();
}
if (index = = choices.length) {
Choices.push ({i:0,
count:values.length});
}
var choice = choices[index++];
return values[choice.i];
}
function fail () {throw fail;}
while (true) {
try {
index = 0;
return func (Amb, fail);
} catch (e) {
if (e!= fail) {
throw e;
}
var choice;
while ((choice = Choices.pop ()) && ++choice.i = = choice.count) {}
if (choice = = undefined) {return
unde fined;
}
Choices.push (choice);}}

and the specific code for the eight-queen problem implemented using AMB

Ambrun (function (Amb, fail) {
var N = 4;
var arr = [];
var turn = [];
for (var n = 0; n < n; n++) {
Turn[turn.length] = n + 1;
}
while (n--) {
Arr[arr.length] = Amb (turn);
}
for (var i = 0; i < n; ++i) {
for (var j = i + 1; j < N; ++j) {
var a = Arr[i], B = arr[j];
if (a = = B | | Math.Abs (a-b) = = J-i) fail ()
;
}
Console.log (arr);
Fail ();
});

The JavaScript solution to the eight Queens problem

This is the eight Queens problem of JavaScript solution, the entire program is not used for loops, are implemented by recursion, the full use of the array object map, reduce, filter, concat, slice method

' Use strict '; var queens = function (boardersize) {///recursive generation of a start to end array var interval = function (start) {if (Start >
End) {return [];}
Return interval (start, end-1). Concat (end);
}; Check if a combination is valid var isValid = function (queencol) {//Check two locations for conflicts var Issafe = function (Pointa, POINTB) {var slop
E = (pointa.row-pointb.row)/(Pointa.col-pointb.col); if ((0 = = slope) | | (1 = = slope) | | ( -1 = = slope))
{return false;}
return true;
};
var len = queencol.length;
var pointtocompare = {row:queencol[len-1], col:len};
First slice out the last column of the array, and then test the point of each column and the point to be measured to see if there is a conflict, the final merge test results return Queencol. Slice (0, len-1). Map (function (row, index) {
Return Issafe ({row:row, Col:index + 1}, Pointtocompare);
). reduce (function (A, b) {return a && B;
});
}; Recursively go to a column to generate a rule-compliant combination of var queencols = function (size) {if (1 = = size) {return interval (1, boardersize). Map (functio
N (i) {return [i];}); }//FirstThe set of all previous qualifying columns is then expanded by one column, then reduced by reduction, and the isvalid is filtered out of the combination return Queencols (size-1) that does not conform to the rule. Map (function (queencol) {RET
Urn interval (1, boardersize). Map (function (row) {return queencol.concat (row);
});
). reduce (function (A, b) {return a.concat (b);
). filter (IsValid);
};
Queens function entry return queencols (boardersize);
};
Console.log (Queens (8)); Output result://[[1, 5, 8, 6, 3, 7, 2, 4],//[1, 6, 8, 3, 7, 4, 2, 5],//...//[8, 3, 1, 6, 2, 5, 7, 4],//[8,
4, 1, 3, 6, 2, 7, 5]]

PS: Extended N Queens Problem

when the 1848 chess player Max Bezzel raised the question of the eight Queens (eight queens puzzle), he could not have imagined that, more than 100 years later, the problem became one of the most important required courses in programming learning. The eight Queens question sounds very simple: put the eight queens on the chess board so that the eight queens do not attack each other (the chess board is a 8x8 square, the Queen can take any number of steps in any direction in eight directions). Although there are 92 solutions to this problem, it is not easy to find a solution with your bare hands. The following figure is one of the solutions:

There are many variants of the eight Queens problem, but no one can be more handsome than the following variant: ask you to design a scheme in which each row of an infinity chessboard is placed with a queen, so that all queens do not attack each other. Specifically, suppose the lower left corner of the chessboard is at the origin, there are infinitely many rows from bottom to top, and there are infinitely many columns from left to right. You need to find out how a whole positive integer is arranged a1, A2, A3, ..., so that when you put the first queen in the first row of the A1 column, put the second queen in the second row of the column A2, and so on, Then any two queens will not attack each other.

Here is a very simple and ingenious construct. First, we give a solution to the five Queens problem. And it is very important that one of the queens occupy the lattice in the bottom left corner.

Next, we extend the five Queen's solution to the 25 queen, which is based on the layout of the five Queens themselves:

As a result, the five Queens in the same group apparently did not attack each other, and the queens of the different groups apparently did not attack each other, and this was the 25 queen solution that met the requirement. Note that after the expansion, the previously completed parts have not changed.

And what happens next? Yes, we copied the 25 Queen's solution into five copies and arranged them again according to the five Queen's layout, thus expanding to 125 queens!

The

continues to multiply outward from the filled part, so that a solution to the infinite queen problem can be generated.