Last active
November 29, 2018 00:12
-
-
Save d3x0r/fdc19f5f0c5a99de4df5129ff5b2aa13 to your computer and use it in GitHub Desktop.
Generalized loops to iterate all combinations and permutations
This file contains hidden or 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
// | |
// call initRowPerms( [], /* number of columns to permutate */, /* number from */, /*number to */ ) | |
// | |
//---------------------------------------------------------------------------- | |
// generate combinations to a callback | |
//---------------------------------------------------------------------------- | |
function getCombinations(cb, cols, from, to) { | |
var indexes = []; | |
for (var n = 0; n < cols; n++) indexes.push(from); | |
var curIndex = cols - 1; | |
var comb = new Array(cols); | |
do { | |
for (var n = 0; n < cols; n++) comb[n] = indexes[n]; | |
if (!cb(comb)) return; | |
do { | |
indexes[curIndex]++; | |
if (indexes[curIndex] > to) { | |
indexes[curIndex] = from; | |
curIndex--; | |
if (curIndex < 0) return; | |
continue; | |
} | |
curIndex = indexes.length - 1; | |
break; | |
} while (1); | |
} while (1); | |
} | |
// demonstrate usage of getCombinations | |
// call generator with a callback that saves output for test code below. | |
function runCombinationGenerator(output, cols, from, to) { | |
function saveOutput(val) { | |
output.push(val); | |
return true; // allow continue. ( similar to [].find() ) | |
} | |
getCombinations(saveOutput, cols, from, to); | |
} | |
//---------------------------------------------------------------------------- | |
// generator method. | |
//---------------------------------------------------------------------------- | |
function* genCombinations(cols, from, to) { | |
var indexes = []; | |
for (var n = 0; n < cols; n++) indexes.push(from); | |
var curIndex = cols - 1; | |
var comb = new Array(cols); | |
do { | |
for (var n = 0; n < cols; n++) comb[n] = indexes[n]; | |
yield comb; | |
do { | |
indexes[curIndex]++; | |
if (indexes[curIndex] > to) { | |
indexes[curIndex] = from; | |
curIndex--; | |
if (curIndex < 0) return; | |
continue; | |
} | |
curIndex = indexes.length - 1; | |
break; | |
} while (1); | |
} while (1); | |
} | |
// demonstrate usage of genCombinations (generator) | |
// call generator with a callback that saves output for test code below. | |
function runCombinations(output, cols, from, to) { | |
var iter = genCombinations(cols, from, to); | |
var next; | |
while ((next = iter.next()).value) { | |
output.push(next.value); | |
} | |
} | |
//---------------------------------------------- | |
// BEGIN Test code..... | |
//---------------------------------------------- | |
var comb = []; | |
runCombinations(comb, 4, 1, 9); | |
console.log("combination length 4 of 1-9 elements %d total", comb.length); | |
console.log(JSON.stringify(comb)); | |
//---------------------------------------------- | |
// END Test code..... | |
//---------------------------------------------- | |
//---------------------------------------------------------------------------- | |
// generator method. | |
//---------------------------------------------------------------------------- | |
// utility function to test if duplicate is in array. | |
function findPair(array, a, b, cols) { | |
//console.log( "find:", a, b, cols ); | |
if (a == b) return findPair(array, a, b + 1, cols); | |
if (b >= cols) { | |
if (a < cols - 1) return findPair(array, a + 1, 0, cols); | |
return false; | |
} | |
if (array[a] == array[b]) return true; | |
if (b + 1 != a) return findPair(array, a, b + 1, cols); | |
else return findPair(array, a, b + 2, cols); | |
} | |
function* genPermutations(cols, range) { | |
var indexes = []; | |
for (var n = 0; n < cols; n++) indexes.push(0); | |
var curIndex = cols - 1; | |
var perm = new Array(cols); | |
do { | |
if (!findPair(indexes, 0, 1, cols, range)) { | |
for (var p = 0; p < cols; p++) perm[p] = indexes[p]; | |
yield perm; | |
} | |
do { | |
indexes[curIndex]++; | |
if (indexes[curIndex] == range) { | |
indexes[curIndex] = 0; | |
curIndex--; | |
if (curIndex < 0) return; | |
continue; | |
} | |
curIndex = indexes.length - 1; | |
break; | |
} while (1); | |
} while (1); | |
} | |
// demonstrate usage of getCombinations (generator) | |
// call generator with a callback that saves output for test code below. | |
function runPermutationGenerator(output, cols, range) { | |
var iter = genPermutations(cols, range); | |
var next; | |
while ((next = iter.next()).value) { | |
output.push(next.value); | |
} | |
} | |
//---------------------------------------------------------------------------- | |
// generate combinations to a callback | |
//---------------------------------------------------------------------------- | |
function getPermutations(cb, cols, range) { | |
var indexes = []; | |
for (var n = 0; n < cols; n++) indexes.push(0); | |
var curIndex = cols - 1; | |
var perm = new Array(cols); | |
do { | |
if (!findPair(indexes, 0, 1, cols, range)) { | |
for (var p = 0; p < cols; p++) perm[p] = indexes[p]; | |
cb(perm); | |
} | |
do { | |
indexes[curIndex]++; | |
if (indexes[curIndex] == range) { | |
indexes[curIndex] = 0; | |
curIndex--; | |
if (curIndex < 0) return; | |
continue; | |
} | |
curIndex = indexes.length - 1; | |
break; | |
} while (1); | |
} while (1); | |
} | |
// demonstrate usage of getPerms | |
// call generator with a callback that saves output for test code below. | |
function runPermutations(output, cols, range) { | |
function saveOutput(val) { | |
output.push(val); | |
return true; // allow continue. ( similar to [].find() ) | |
} | |
getPermutations(saveOutput, cols, range); | |
} | |
//---------------------------------------------------------------------------- | |
// generator method. | |
//---------------------------------------------------------------------------- | |
// call initPerms( [], 5 ) ; // permuatations of 0-4 | |
function initPerms(output, cols, range) { | |
var indexes = []; | |
for (var n = 0; n < cols; n++) indexes.push(0); | |
var curIndex = cols - 1; | |
do { | |
if (!findPair(indexes, 0, 1, cols, range)) { | |
var perm = indexes.map(v => v); | |
output.push(perm); | |
} | |
do { | |
indexes[curIndex]++; | |
if (indexes[curIndex] == range) { | |
indexes[curIndex] = 0; | |
curIndex--; | |
if (curIndex < 0) return; | |
continue; | |
} | |
curIndex = indexes.length - 1; | |
break; | |
} while (1); | |
} while (1); | |
} | |
//----------------------- | |
// BEGIN TEST CODE | |
//----------------------- | |
var perms = []; | |
initPerms(perms, 4, 9); | |
console.log("permutation length 4 of 9 elements %d total", perms.length); | |
perms = []; | |
runPermutationGenerator(perms, 4, 9); | |
console.log("permutation length 4 of 9 elements %d total", perms.length); | |
perms = []; | |
runPermutations(perms, 4, 9); | |
console.log("permutation length 4 of 9 elements %d total", perms.length); | |
console.log(JSON.stringify(perms)); | |
//----------------------- | |
// END TEST CODE | |
//----------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment