Javascript solves Level 3 Magic Square (jiugongge) and level 3 Magic Square
Puzzle: Level 3 magic. Try to use level 1 ~ 9 fill in the nine different integers in a 3 × 3 table, so that the sum of numbers on each row, column, and each diagonal line is the same.
Policy: search by exhaustive means. List all integer filling schemes and filter them.
The highlight is the design of the recursive function getPermutation. At last, this article provides several non-recursive algorithms.
// Recursive algorithm, clever, but overcharged Resource function getPermutation (arr) {if (arr. length = 1) {return [arr];} var permutation = []; for (var I = 0; I <arr. length; I ++) {var firstEle = arr [I]; // obtain the first element var arrClone = arr. slice (0); // copy the array arrClone. splice (I, 1); // Delete the first element and reduce the array scale var childPermutation = getPermutation (arrClone); // recursive for (var j = 0; j <childPermutation. length; j ++) {childPermutation [j]. unshift (firstEle );/ /Insert the retrieved element back} permutation = permutation. concat (childPermutation);} return permutation;} function validateCandidate (candidate) {var sum = candidate [0] + candidate [1] + candidate [2]; for (var I = 0; I <3; I ++) {if (! (SumOfLine (candidate, I) = sum & sumOfColumn (candidate, I) = sum) {return false ;}} if (sumOfDiagonal (candidate, true) = sum & sumOfDiagonal (candidate, false) = sum) {return true;} return false;} function sumOfLine (candidate, line) {return candidate [line * 3] + candidate [line * 3 + 1] + candidate [line * 3 + 2];} function sumOfColumn (candidate, col) {return candidate [col] + candidate [col + 3] + candidate [col + 6];} function sumOfDiagonal (candidate, isForwardSlash) {return isForwardSlash? Candidate [2] + candidate [4] + candidate [6]: candidate [0] + candidate [4] + candidate [8];} var permutation = getPermutation ([1, 2, 3, 4, 5, 6, 7, 8, 9]); var candidate; for (var I = 0; I <permutation. length; I ++) {candidate = permutation [I]; if (validateCandidate (candidate) {break;} else {candidate = null;} if (candidate) {console. log (candidate);} else {console. log ('no valid result found ');}/ /Modulo (non-recursive) Full permutation algorithm/* specific example of an algorithm: * obtain four elements ["a", "B", "c ", "d"] in full order, a total of 4 cycles! = 24 times. It can start from any integer index> = 0 and accumulate 1 at a time until the cycle ends after index + 23; * assume that the index is 13 (or 13 + 24, 13 + 224,13 + 3*24 ...), Because there are four elements in total, so the iteration is four times, the resulting sorting process is: * 1st iterations, 13/1, operator = 13, remainder = 0, therefore, if 1st elements are inserted at 0th locations (I .e., the subscript is 0), ["a"]; * 2nd iterations, 13/2, operator = 6, remainder = 1, therefore, if 2nd elements are inserted at 1st locations (I .e., the subscript is 1), ["a", "B"]; * 3rd iterations, 6/3, operator = 2, the remainder is 0. Therefore, 3rd elements are inserted at 0th locations (I .e., the subscript is 0). ["c", "a", "B"]; * 4th iterations, 2/4, quotient = 0, remainder = 2, so 4th elements are inserted into 2nd positions (I .e., subscript is 2), get ["c", "a", "d ", "B"]; */function perm (arr) {var result = new Array (arr. length); var fac = 1; for (var I = 2; I <= arr. length; I ++) // calculates the number of fac * = I based on the array length. for (var Index = 0; index <fac; index ++) {// each index corresponds to an array var t = index; for (I = 1; I <= arr. length; I ++) {// determine the position of each number. var w = t % I; for (var j = I-1; j> w; j --) // shift, leave space for result [w] result [j] = result [j-1]; result [w] = arr [I-1]; t = Math. floor (t/I);} if (validateCandidate (result) {console. log (result); break ;}} perm ([1, 2, 3, 4, 5, 6, 7, 8, 9]); // clever backtracking algorithm, non-recursive solution to fully arrange function seek (index, n ){ Var flag = false, m = n; // flag is the marker for finding the position arrangement. m stores the position being searched, and index [n] is the element (location encoding) do {index [n] ++; // set the current position element if (index [n] = index. length) // available index [n --] =-1; // reset the current position and roll back to the previous position else if (! (Function () {for (var I = 0; I <n; I ++) // determine whether the current position is set in conflict with the previous position if (index [I] = index [n]) return true; // conflict, directly return to the loop and re-set the element value return false; // no conflict, check whether the current position is the end of the queue, yes, find an arrangement; no, the current position is moved back })()) // if (m = n) is not selected for this position. // The current position is searched. flag = true; else n ++; // the current and previous position elements are arranged, position move back} while (! Flag & n> = 0) return flag;} function perm (arr) {var index = new Array (arr. length); for (var I = 0; I <index. length; I ++) index [I] =-1; for (I = 0; I <index. length-1; I ++) seek (index, I); // initialize to 1, 2, 3 ,..., -1: The last element is-1. Note that it is small to large. If the element is not a number, it can be understood as its position subscript while (seek (index, index. length-1) {var temp = []; for (I = 0; I <index. length; I ++) temp. push (arr [index [I]); if (validateCandidate (temp) {console. log (temp); break ;}} perm ([1, 2, 3, 4, 5, 6, 7, 8, 9]);
/*
Full Permutation (non-recursive order) Algorithm
1. Create a location array, that is, arrange the positions, and convert them to the arrangement of elements;
2. Perform full sorting according to the following algorithms:
Set P to 1 ~ A full arrangement of n (Location Number): p = p1, p2... pn = p1, p2... PJ-1, pj, pj + 1... pk-1, pk, pk + 1... pn
(1) from the end of the arrangement, find the first index j, which is smaller than the number on the right (j starts from the header ), that is, j = max {I | pi <pi + 1}
(2) In the position number on the Right of pj, find all the INDEX k with the smallest position number greater than pj, that is, k = max {I | pi> pj}
The position number on the Right of pj increases progressively from right to left, so k is the largest index among all the position numbers greater than pj.
(3) Switch pj and pk
(4) then pj + 1... pk-1, pk, pk + 1... pn flipped to get the P' = p1, p2... PJ-1, pj, pn... pk + 1, pk, pk-1... pj + 1
(5) P' is the next arrangement of p.
For example:
24310 is the position number 0 ~ 4. The following steps are taken to find the next arrangement:
(1) from the right to the left, find the first number that is smaller than the number on the right. 2;
(2) Find the smallest 3 of the two digits after the number;
(3) Exchange 2 and 3 for 34210;
(4) flip all the numbers behind the original 2 (current 3), that is, flip 4210 to 30124;
(5) The next order of 24310 is 30124.
*/
Function swap (arr, I, j) {var t = arr [I]; arr [I] = arr [j]; arr [j] = t ;} function sort (index) {for (var j = index. length-2; j> = 0 & index [j]> index [j + 1]; j --); // This loop starts from the end of the position array, locate the position on the left that is less than the right, that is, j if (j <0) return false; // all rows have been completed for (var k = index. length-1; index [k] <index [j]; k --); // This loop starts from the end of the position array and finds the smallest position greater than the j position, that is, k swap (index, j, k); for (j = j + 1, k = index. length-1; j <k; j ++, k --) swap (index, j, k ); // return true for all positions from j + 1 to the end of this loop;} function perm (arr) {var index = new Array (arr. length); for (var I = 0; I <index. length; I ++) index [I] = I; do {var temp = []; for (I = 0; I <index. length; I ++) temp. push (arr [index [I]); if (validateCandidate (temp) {console. log (temp); break;} while (sort (index);} perm ([1, 2, 3, 4, 5, 6, 7, 8, 9]);
The above is all the content of this article. I hope you will like it.