| // Recursive algorithms, clever but resource-consuming 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 to reduce the array size Var childPermutation = getPermutation (arrClone); // Recursion 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) permutation algorithm /* Example of an algorithm: * Find the full arrangement of the four elements ["a", "B", "c", "d"], repeating 4 in total! = 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, the process of this arrangement is obtained after four iterations: * For 1st iterations, 13/1, quotient = 13, and remainder = 0, 1st elements are inserted at 0th positions (I .e., the subscript is 0). ["a"] is obtained. * For 2nd iterations, 13/2, quotient = 6, and remainder = 1, 2nd elements are inserted at 1st positions (I .e., the subscript is 1). ["", "B"]; * 3rd iterations, 6/3, quotient = 2, and remainder = 0. Therefore, 3rd elements are inserted at 0th positions (I .e., the subscript is 0). ["c", "", "B"]; * For 4th iterations, 2/4, quotient = 0, and remainder = 2, 4th elements are inserted at 2nd positions (I .e., subscript is 2). ["c", "", "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 arrays based on the array length. Fac * = I; For (var index = 0; index <fac; index ++) {// each index corresponds to an arrangement 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 to 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 for full Arrangement 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] ++; // sets the current position Element If (index [n] = index. length) // No location is 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 in conflict with the previous position If (index [I] = index [n]) return true; // conflict, directly return to the loop to reset the element value Return false; // no conflict. Check whether the current position is the end of the queue. If yes, locate an arrangement. If no, move the current position back. }) () // This location is not selected If (m = n) // The current position is searched Flag = true; Else N ++; // the current and previous position elements have been arranged, and the position is moved 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]); |