Assumptions
You have an array of numbers as input
Every call to makeRandom
should randomly select two numbers from your array and output the sum
Every subsequent call to makeRandom
should not use any number (id
) already used
list = [1,1,2,3,4,5];
// The number 1 could be used twice (but only in different calls to makeRandom)
// The numbers 2,3,4,5 can only be used once
list = [1,1];
// Shouldn't work because 1 == 1
JS Code
var list = [1,2,3,4,5,6,7,8,9]; // Your seed list
var usable = list.slice(0); // Copy of your seed list {which we will alter with makeRandom}
function makeRandom(){
// Check it's possible...
let counts = {}; // Create object to count unique numbers
for (var i = 0; i < usable.length; i++) {
counts[usable[i]] = 1 + (counts[usable[i]] || 0); // Iterate array and fill counts
}
if(Object.keys(counts).length < 2){ // Check there are at least two unique numbers
console.log("List is too short!"); // Log error if <2
return false; // Exit function if <2
}
// Get random numbers and output sum...
let id = Math.floor(Math.random() * usable.length) // Randomly select an id from usable numbers
let a = usable[id]; // Set first number
usable.splice(id, 1); // Remove 1st number from usable numbers
let b;
while(true){ // Loop until numbers are different
id = Math.floor(Math.random() * usable.length); // Randomly select an id from usable numbers
b = usable[id]; // Set second number
if(a !== b)break; // Check 1st number isn't the same as the second number
}
usable.splice(id, 1); // Remove 2nd number from usable numbers
// console.log(a + " + " + b + " = " + (a+b)); // Log for debugging if required
return a+b; // Return sum of 1st and 2nd numbers
}
Note: I've typed out the while loop in full for ease of understanding; it could be shortened using do...while(...)
:
let b;
do b = list[Math.floor(Math.random() * list.length)]; // Set second number
while(a==b) // Re-set second number if a == b OR if b was used in the last call to makeRandom
Example
var list = [1,2,3,4,5,6,7,8,9];
var usable = list.slice(0);
function makeRandom(){
let counts = {};
for (var i = 0; i < usable.length; i++) {
counts[usable[i]] = 1 + (counts[usable[i]] || 0);
}
if(Object.keys(counts).length < 2){
console.log("List is too short!");
return false;
}
let id = Math.floor(Math.random() * usable.length)
let a = usable[id];
usable.splice(id, 1);
let b;
while(true){
id = Math.floor(Math.random() * usable.length);
b = usable[id];
if(a !== b)break;
}
usable.splice(id, 1);
console.log(a + " + " + b + " = " + (a+b));
return a+b;
}
// Make several calls to function
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();
// Change the seed lists
var list = [1,1,1,1,1,9];
var usable = list.slice(0);
// Make several calls to function
makeRandom();
makeRandom();
makeRandom();
Example Output
__Example 1__
list = [1,2,3,4,5,6,7,8,9]; // Example list used
// console.log return
> makeRandom(); // 4 + 2 = 6 6
> makeRandom(); // 1 + 8 = 9 9
> makeRandom(); // 9 + 3 = 12 12
> makeRandom(); // 6 + 7 = 13 13
> makeRandom(); // List is too short! false
> makeRandom(); // List is too short! false
__Example 2__
list = [1,1,1,1,1,9]; // Example list used
// console.log return
> makeRandom(); // 1 + 9 = 10 10
> makeRandom(); // List is too short! false
> makeRandom(); // List is too short! false
Alternative
Having had a look at the updates to your question...
I'm not clear on whether the numbers can only be used once or if they just can't be used back to back.
list = [1,2,3,4,5];
// Choose from // Chosen
> makeRandom(); // 1, 2, 3, 4, 5 // 1, 4
> makeRandom(); // 2, 3, 5 // 2, 3
> makeRandom(); // 1, 4, 5 // 1, 5
If that's the case then the following is likely more useful
var list = [1,2,3,4,5,6,7,8,9]; // Your seed list
var used = []; // Last used pair of numbers
function makeRandom(){
// Check it's possible...
let counts = {}; // Create object to count unique numbers
for (var i = 0; i < list.length; i++) {
counts[list[i]] = 1 + (counts[list[i]] || 0); // Iterate array and fill counts
}
if(Object.keys(counts).length < 4){ // Check there are at least four unique numbers: any less and we'll end up in an infinite loop on the second call of makeRandom
console.log("List is too short!"); // Log error if <2
return false; // Exit function if <2
}
// Get random numbers and output sum...
let a;
do a = list[Math.floor(Math.random() * list.length)]; // Set first number
while(used.includes(a)) // Reset first number if a was used in the last call to makeRandom
let b;
do b = list[Math.floor(Math.random() * list.length)]; // Set second number
while(a==b || used.includes(b)) // Re-set second number if a == b OR if b was used in the last call to makeRandom
used = [a, b]; // Set last used numbers
console.log(a + " + " + b + " = " + (a+b)); // Log for debugging if required
return a+b; // Return sum of 1st and 2nd numbers
}
// Make several calls to function
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();
makeRandom();
// Change the seed lists
var list = [1,2,3,4];
// Make several calls to function
// Notice with only 4 numbers once the first pair is selected (e.g. 1 & 3) the pattern cycles 1,3 -> 2,4 -> 1,3 -> 2,4
makeRandom();
makeRandom();
makeRandom();