You have an infinite loop because numPosTemp
after the first iteration of your while-loop will remain with two elements for the next iteration of your loop. As a result, your inner while loop doesn't run, as numPostTemp
is already greater/equal to two. Your if-statement check in your for
loop is also true, as you're checking if the array you just pushed into numPos
exists in your numPos
. This results in k
increasing, and so your final if-statement check is false. As nothing changed for this iteration of your loop, you end up in an infinite loop, as numPos
can't increase. To fix this, move numPosTemp
into your while loop.
Moreover, your .every()
method is checking that all elements from your current numPosTemp
exists within your numPos
array. If one element doesn't exist, the every method will return valse and your numPosTemp
array will still be added, meaning [1, 2], [1, 3]
can occur. To fix this (so 1 doesn't double-up), change .every()
to .some()
let numPos = [];
let r, j, k;
// generate 5 sets
while (numPos.length < 5) {
let numPosTemp = [];
// generate 2 diff num pos
while (numPosTemp.length < 2) {
r = Math.floor(Math.random() * 10);
if (numPosTemp.indexOf(r) === -1) {
numPosTemp.push(r);
}
}
// check match any child array
k = 0;
for (j = 0; j < numPos.length; j++) {
if (numPosTemp.some(function (element) {
return numPos[j].includes(element);
}) == true) {
k++;
}
}
// will only add into numPos if totally no match
if (k == 0) {
numPos.push(numPosTemp);
}
}
console.log(numPos);
A more efficient solution would be to generate an array of 10 numbers from 0 to 9. You can then shuffle this array to randomize it, and then chunk the array into twos:
function shuffle(array) {
// From: https://stackoverflow.com/a/12646864/5648954
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function chunk(arr, n) {
return arr.length ? [arr.slice(0, n), ...chunk(arr.slice(n), n)] : [];
}
const groups = 5; // 5 groups
const nums = Array.from({length: groups * 2}, (_, i) => i); // [0, 1, 2, ... 9]
const res = chunk(shuffle(nums), 2);
console.log(res);
If you want numbers to be able to double up, you can maintain a Set of strings. The strings represent string versions of your inner arrays [x, y] -> "x,y"
. For each number pair you want to create, you can check if the formatted string version of your numbers is in the set. Using a set has an efficient look-up compared to an array. If the formatted string appears in the set, then you can generate your random numebrs until you have two numbers not in your set. Once you find two numbers, you can add these to your set and use them a a pair of numbers in your end result:
const groups = 5; // 5 groups
const seen = new Set();
const format = (...args) => args.join();
const nums = Array.from({length: groups}, () => {
let x, y;
do {
x = Math.floor(Math.random() * groups*2);
y = Math.floor(Math.random() * groups*2);
} while(x !== y && seen.has(format(x,y)));
seen.add(format(x, y));
return [x, y];
});
console.log(nums);