Generating non-repeating random numbers in JS - javascript

I have the following function
function randomNum(max, used){
newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
console.log(newNum + " is not in array");
return newNum;
}else{
return randomNum(max,used);
}
}
Basically I am creating a random number between 1 - 10 and checking to see if that number has already been created, by adding it to an array and checking the new created number against it. I call it by adding it to a variable..
UPDATED:
for(var i=0;i < 10;i++){
randNum = randomNum(10, usedNums);
usedNums.push(randNum);
//do something with ranNum
}
This works, but in Chrome I get the following error:
Uncaught RangeError: Maximum call stack size exceeded
Which I guess it's because I am calling the function inside itself too many times. Which means my code is no good.
Can someone help me with the logic? what's a best way to make sure my numbers are not repeating?

If I understand right then you're just looking for a permutation (i.e. the numbers randomised with no repeats) of the numbers 1-10?
Maybe try generating a randomised list of those numbers, once, at the start, and then just working your way through those?
This will calculate a random permutation of the numbers in nums:
var nums = [1,2,3,4,5,6,7,8,9,10],
ranNums = [],
i = nums.length,
j = 0;
while (i--) {
j = Math.floor(Math.random() * (i+1));
ranNums.push(nums[j]);
nums.splice(j,1);
}
So, for example, if you were looking for random numbers between 1 - 20 that were also even, then you could use:
nums = [2,4,6,8,10,12,14,16,18,20];
Then just read through ranNums in order to recall the random numbers.
This runs no risk of it taking increasingly longer to find unused numbers, as you were finding in your approach.
EDIT: After reading this and running a test on jsperf, it seems like a much better way of doing this is a Fisher–Yates Shuffle:
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
Basically, it's more efficient by avoiding the use of 'expensive' array operations.
BONUS EDIT: Another possibility is using generators (assuming you have support):
function* shuffle(array) {
var i = array.length;
while (i--) {
yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
}
}
Then to use:
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
ranNums.next().value; // first random number from array
ranNums.next().value; // second random number from array
ranNums.next().value; // etc.
where ranNums.next().value will eventually evaluate to undefined once you've run through all the elements in the shuffled array.
Overall this won't be as efficient as the Fisher–Yates Shuffle because you're still splice-ing an array. But the difference is that you're now doing that work only when you need it rather than doing it all upfront, so depending upon your use case, this might be better.

//random number without repetition in JavaScript, Just in one line;
//it can be used as _id;
//it not need to store or check;
const myRnId = () => parseInt(Date.now() * Math.random());
console.log(myRnId()); // any random number included timeStamp;

function Myrand(max,min){
arr=[];
for (i = 0; i < max; i++) {
x = Math.floor( Math.random() * max) + min;
if(arr.includes(x) == true){
i=i-1;
}else{
if(x>max==false){
arr.push(x);
}
}
}
return arr;
}
console.log(Myrand(5,1));

Try this:
var numbers = []; // new empty array
var min, max, r, n, p;
min = 1;
max = 50;
r = 5; // how many numbers you want to extract
for (let i = 0; i < r; i++) {
do {
n = Math.floor(Math.random() * (max - min + 1)) + min;
p = numbers.includes(n);
if(!p){
numbers.push(n);
}
}
while(p);
}
console.log(numbers.join(" - "));

let arr = [];
do {
let num = Math.floor(Math.random() * 10 + 1);
arr.push(num);
arr = arr.filter((item, index) => {
return arr.indexOf(item) === index
});
} while (arr.length < 10);
console.log(arr);

HTML
<p id="array_number" style="font-size: 25px; text-align: center;"></p>
JS
var min = 1;
var max = 90;
var stop = 6; //Number of numbers to extract
var numbers = [];
for (let i = 0; i < stop; i++) {
var n = Math.floor(Math.random() * max) + min;
var check = numbers.includes(n);
if(check === false) {
numbers.push(n);
} else {
while(check === true){
n = Math.floor(Math.random() * max) + min;
check = numbers.includes(n);
if(check === false){
numbers.push(n);
}
}
}
}
sort();
//Sort the array in ascending order
function sort() {
numbers.sort(function(a, b){return a-b});
document.getElementById("array_number").innerHTML = numbers.join(" - ");
}
DEMO

The issue is that as you approach saturation you begin to take longer and longer to generate a unique number "randomly". For instance, in the example you provided above the max is 10. Once the used number array contains 8 numbers it can potentially take a long time for the 9th and 10th to be found. This is probably where the maximum call stack error is being generated.
jsFiddle Demo showing iteration count being maxed
By iterating inside of your recursion, you can see that a large amount of execution occurs when the array is completely saturated, but the function is called. In this scenario, the function should exit.
jsFiddle Demo with early break
if( used.length >= max ) return undefined;
And one last way to accomplish both the iteration checks and the infinite recursion would be like this jsFiddle Demo:
function randomNum(max, used, calls){
if( calls == void 0 ) calls = 0;
if( calls++ > 10000 ) return undefined;
if( used.length >= max ) return undefined;
var newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
return newNum;
}else{
return randomNum(max,used,calls);
}
}

<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Math.random()</h2>
<p>Math.random() returns a random number between 0 (included) and 1 (excluded):</p>
<p id="demo"></p>
<script>
var storeArray = []
function callRamdom(){
var randomNumber = Math.floor(Math.random() * 5);
return randomNumber;
}
function randomStore(){
var localValue = callRamdom()
var status = false;
for(i=0;i<5; i++){
var aa = storeArray[i];
if(aa!=localValue){
console.log(storeArray[i]+"hhhhh"+ localValue);
if(i==4){
status=true;
}
}
else
break;
}
if(status==true){
storeArray.push(localValue);
}
if(storeArray.length!=5){
randomStore();
}
return storeArray;
}
document.getElementById("demo").innerHTML = randomStore();
</script>
</body>
</html>

while(randArr.length < SIZEOFARRAY){
val = Math.floor((Math.random() * RANGEOFVALUES));
if(randArr.indexOf(val) < 0){
randArr.push(val);
}
}
You can change SIZEOFARRAY to the size of the array you wish to use
and also change RANGEOFVALUES to the range of values you wish to randomize

const GenerateRandomNumbers = (max) => {
let orderNumbers = new Set();
for (let i = 1; ;i++){
let random = Math.floor(Math.random() * max + 1) ;
orderNumbers.add(random);
if (orderNumbers.size == max){
break;
}
}
return orderNumbers;}

function randomNumbers(max) {
function range(upTo) {
var result = [];
for(var i = 0; i < upTo; i++) result.push(i);
return result;
}
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
var myArr = shuffle(range(max));
return function() {
return myArr.shift();
};
}
Built a little test, try this on jsfiddle:
var randoms = randomNumbers(10),
rand = randoms(),
result = [];
while(rand != null) {
result.push(rand);
rand = randoms();
}
console.log(result);
Shuffle function courtesy of dzone.com.

This is how I achieve it using underscore.js
To get n integers from min to max values. Where n is the size argument.
var randomNonRepeatingIntFromInterval = function(min, max, size) {
var values = [];
while (values.length < size) {
values.push(Math.floor(Math.random() * ( max - min + 1) + min));
values = _.uniq(values);
}
return values;
}

Sorry this is a new answer to an old question, but this can be done more efficiently with a map. What you're after is random selection rather than non-repeating random. Non-repeating random is nonsensical.
Where _a is the collection, and r is not part of the collection, we lambda the random value r:
function aRandom(f){
var r = Math.random();
aRandom._a[r] ? aRandom(f) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
aRandom(function(r){ console.log(r) });
Redefine aRandom._a when the browser gets sluggish. To avoid eventual sluggishness, one should really use an UUID generation algo with sufficient entropy so that chances of repeat are effectively zero, rather than brute forcing differentiability. I chose the function name aRandom because latin prefix A- means "away from." Since the more it's used, the further away from random the output. The function produces one million unique values in 2100 ms on a Macbook.
Advantage of the above solution is no need to limit the set. As well, multiple callers can use it at the same time and assume their values are different from all other callers. This is handy for such things as noise jittering distributions with insured no overlaps.
However, it can be modified to return integers as well, so as to restrict ram use to the length supplied:
function aRandom(f,c){
var r = Math.floor(Math.random()*c);
aRandom._a[r] ? aRandom(f,c) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
var len = 10;
var resultset = [];
for(var i =0; i< len; i++){
aRandom(function(r){ resultset.push(r); }, len);
}
console.log(resultset);

randojs.com makes this a simple one-liner:
randoSequence(1, 10)
This will return an array of numbers from 1 through 10 in random order.
You just need to add the following to the head of your html document, and you can do pretty much whatever you want with randomness easily. Random values from arrays, random jquery elements, random properties from objects, and even preventing repetitions as I've shown here.
<script src="https://randojs.com/1.0.0.js"></script>

Just one solution for reference
const fiveNums = () => {
const ranNum = () => Math.floor(Math.random() * (10 + 1));
let current;
let arr = [];
while(arr.length < 5) {
if(arr.indexOf(current = ranNum()) === -1) {
arr.push(current);
}
}
return arr;
};
fiveNums();

In case no permutation is wanted and/or length shall be variable, here is a solution for non repeating randomized lists/arrays without if-statements:
Shuffle function:
Input:
Array or object(list) of arbitrary length
optional: last key to be filtered (Array: index number, List: String of key)
Output:
random Key
to get your random item use myArrayOrList[key]
// no repeat if old_key is provided
function myShuffle(arr_or_list, old_key = false) {
var keys = Array.from(Object.keys(arr_or_list)); //extracts keys
if (old_key != false) {
keys.splice(keys.indexOf(old_key), 1); // removes old_key from keys
};
var randomKey = keys[Math.floor(Math.random() * keys.length)]; // get random key
return randomKey;
}
//test:
const a = [10, 20, 30, 40, 50, 60];
const b = {
"a": 10,
"bla-bla bla": 20,
"d": 30,
"c": 40
};
var oldKeys_a = [];
var oldKeys_b = [];
oldKeys_a[0] = myShuffle(a);
oldKeys_b[0] = myShuffle(b);
var i;
for (i = 1; i < 10; i++) {
oldKeys_a[i] = myShuffle(a, oldKeys_a[i - 1]);
oldKeys_b[i] = myShuffle(b, oldKeys_b[i - 1]);
}
alert('oldKeys_a: ' + oldKeys_a + '; oldKeys_b: ' + oldKeys_b)
//random...
//>>> oldKeys_a: 1,3,0,0,5,0,4,5,2,3; oldKeys_b: d,a,d,bla-bla bla,a,c,d,bla-bla bla,a,d <<<

Non-repeating range random number generation with the recursive patterns.
const getRandom = (max, memo) => {
if (max != memo.length) {
const pos = Math.floor(Math.random() * max);
if (memo.includes(pos)) {
return getRandom(max, memo);
} else {
return pos;
}
}
}
const random = [];
const range = 6;
for (let index = 0; index < range; index++) {
random.push(getRandom(range, random))
}
console.log('random', random) // random (6) [5, 3, 0, 2, 1, 4]

function getRandomNumberNoRepeat(length){
let numberPick = [0,1,2,3,4,5,6,7,8,9]
return numberPick.sort(() => Math.random() -0.5).slice(0, length)}
console.log(getRandomNumberNoRepeat(3));

let display = document.getElementById("container");
let myArray = [];
let randomiser = (min, max, vals) => {
while (myArray.length < vals) {
let randNum = Math.floor(Math.random() * (max - min + 1) + min);
if (!myArray.includes(randNum)) {
myArray.push(randNum);
}
}
return (display.textContent = myArray.join(" - "));
};
randomiser(1, 35, 7);
Here is one where you can specify how many number you need.
I decided to write this code and make a chrome extension for it to use when playing the lotto. haha. Just a learning experience for me and thanks to all who contributed. I read all posts and I'm better of today than I was yesterday in understanding shuffle and random non repeating numbers.

You don't really want a lost of random numbers. Truly random numbers must be able to repeat.
Truly random number are like throwing dice. Any number can come up next.
Shuffled numbers are like drawing playing cards. Each number can come up only once.
What you are really asking for is to shuffle a list of numbers and then use the first so many numbers from the shuffled list.
Think of making a list of numbers in order, and then using the random number generator to randomly select a number from a copy of that list. Each time, put the selected number at the end of your new list and remove it from the copy of the old list, shortening that list. When you are done, the new list will contain the shuffled numbers and the copy of the old list will be empty.
Alternately, you can take the number selected and use it immediately, shortening the copy of the list by removing the used number. Because you have removed the number from the list, it can't come up again.

Related

How to prevent Math.random from repeating a return? [duplicate]

I have the following function
function randomNum(max, used){
newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
console.log(newNum + " is not in array");
return newNum;
}else{
return randomNum(max,used);
}
}
Basically I am creating a random number between 1 - 10 and checking to see if that number has already been created, by adding it to an array and checking the new created number against it. I call it by adding it to a variable..
UPDATED:
for(var i=0;i < 10;i++){
randNum = randomNum(10, usedNums);
usedNums.push(randNum);
//do something with ranNum
}
This works, but in Chrome I get the following error:
Uncaught RangeError: Maximum call stack size exceeded
Which I guess it's because I am calling the function inside itself too many times. Which means my code is no good.
Can someone help me with the logic? what's a best way to make sure my numbers are not repeating?
If I understand right then you're just looking for a permutation (i.e. the numbers randomised with no repeats) of the numbers 1-10?
Maybe try generating a randomised list of those numbers, once, at the start, and then just working your way through those?
This will calculate a random permutation of the numbers in nums:
var nums = [1,2,3,4,5,6,7,8,9,10],
ranNums = [],
i = nums.length,
j = 0;
while (i--) {
j = Math.floor(Math.random() * (i+1));
ranNums.push(nums[j]);
nums.splice(j,1);
}
So, for example, if you were looking for random numbers between 1 - 20 that were also even, then you could use:
nums = [2,4,6,8,10,12,14,16,18,20];
Then just read through ranNums in order to recall the random numbers.
This runs no risk of it taking increasingly longer to find unused numbers, as you were finding in your approach.
EDIT: After reading this and running a test on jsperf, it seems like a much better way of doing this is a Fisher–Yates Shuffle:
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
Basically, it's more efficient by avoiding the use of 'expensive' array operations.
BONUS EDIT: Another possibility is using generators (assuming you have support):
function* shuffle(array) {
var i = array.length;
while (i--) {
yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
}
}
Then to use:
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
ranNums.next().value; // first random number from array
ranNums.next().value; // second random number from array
ranNums.next().value; // etc.
where ranNums.next().value will eventually evaluate to undefined once you've run through all the elements in the shuffled array.
Overall this won't be as efficient as the Fisher–Yates Shuffle because you're still splice-ing an array. But the difference is that you're now doing that work only when you need it rather than doing it all upfront, so depending upon your use case, this might be better.
//random number without repetition in JavaScript, Just in one line;
//it can be used as _id;
//it not need to store or check;
const myRnId = () => parseInt(Date.now() * Math.random());
console.log(myRnId()); // any random number included timeStamp;
function Myrand(max,min){
arr=[];
for (i = 0; i < max; i++) {
x = Math.floor( Math.random() * max) + min;
if(arr.includes(x) == true){
i=i-1;
}else{
if(x>max==false){
arr.push(x);
}
}
}
return arr;
}
console.log(Myrand(5,1));
Try this:
var numbers = []; // new empty array
var min, max, r, n, p;
min = 1;
max = 50;
r = 5; // how many numbers you want to extract
for (let i = 0; i < r; i++) {
do {
n = Math.floor(Math.random() * (max - min + 1)) + min;
p = numbers.includes(n);
if(!p){
numbers.push(n);
}
}
while(p);
}
console.log(numbers.join(" - "));
let arr = [];
do {
let num = Math.floor(Math.random() * 10 + 1);
arr.push(num);
arr = arr.filter((item, index) => {
return arr.indexOf(item) === index
});
} while (arr.length < 10);
console.log(arr);
HTML
<p id="array_number" style="font-size: 25px; text-align: center;"></p>
JS
var min = 1;
var max = 90;
var stop = 6; //Number of numbers to extract
var numbers = [];
for (let i = 0; i < stop; i++) {
var n = Math.floor(Math.random() * max) + min;
var check = numbers.includes(n);
if(check === false) {
numbers.push(n);
} else {
while(check === true){
n = Math.floor(Math.random() * max) + min;
check = numbers.includes(n);
if(check === false){
numbers.push(n);
}
}
}
}
sort();
//Sort the array in ascending order
function sort() {
numbers.sort(function(a, b){return a-b});
document.getElementById("array_number").innerHTML = numbers.join(" - ");
}
DEMO
The issue is that as you approach saturation you begin to take longer and longer to generate a unique number "randomly". For instance, in the example you provided above the max is 10. Once the used number array contains 8 numbers it can potentially take a long time for the 9th and 10th to be found. This is probably where the maximum call stack error is being generated.
jsFiddle Demo showing iteration count being maxed
By iterating inside of your recursion, you can see that a large amount of execution occurs when the array is completely saturated, but the function is called. In this scenario, the function should exit.
jsFiddle Demo with early break
if( used.length >= max ) return undefined;
And one last way to accomplish both the iteration checks and the infinite recursion would be like this jsFiddle Demo:
function randomNum(max, used, calls){
if( calls == void 0 ) calls = 0;
if( calls++ > 10000 ) return undefined;
if( used.length >= max ) return undefined;
var newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
return newNum;
}else{
return randomNum(max,used,calls);
}
}
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Math.random()</h2>
<p>Math.random() returns a random number between 0 (included) and 1 (excluded):</p>
<p id="demo"></p>
<script>
var storeArray = []
function callRamdom(){
var randomNumber = Math.floor(Math.random() * 5);
return randomNumber;
}
function randomStore(){
var localValue = callRamdom()
var status = false;
for(i=0;i<5; i++){
var aa = storeArray[i];
if(aa!=localValue){
console.log(storeArray[i]+"hhhhh"+ localValue);
if(i==4){
status=true;
}
}
else
break;
}
if(status==true){
storeArray.push(localValue);
}
if(storeArray.length!=5){
randomStore();
}
return storeArray;
}
document.getElementById("demo").innerHTML = randomStore();
</script>
</body>
</html>
while(randArr.length < SIZEOFARRAY){
val = Math.floor((Math.random() * RANGEOFVALUES));
if(randArr.indexOf(val) < 0){
randArr.push(val);
}
}
You can change SIZEOFARRAY to the size of the array you wish to use
and also change RANGEOFVALUES to the range of values you wish to randomize
const GenerateRandomNumbers = (max) => {
let orderNumbers = new Set();
for (let i = 1; ;i++){
let random = Math.floor(Math.random() * max + 1) ;
orderNumbers.add(random);
if (orderNumbers.size == max){
break;
}
}
return orderNumbers;}
function randomNumbers(max) {
function range(upTo) {
var result = [];
for(var i = 0; i < upTo; i++) result.push(i);
return result;
}
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
var myArr = shuffle(range(max));
return function() {
return myArr.shift();
};
}
Built a little test, try this on jsfiddle:
var randoms = randomNumbers(10),
rand = randoms(),
result = [];
while(rand != null) {
result.push(rand);
rand = randoms();
}
console.log(result);
Shuffle function courtesy of dzone.com.
This is how I achieve it using underscore.js
To get n integers from min to max values. Where n is the size argument.
var randomNonRepeatingIntFromInterval = function(min, max, size) {
var values = [];
while (values.length < size) {
values.push(Math.floor(Math.random() * ( max - min + 1) + min));
values = _.uniq(values);
}
return values;
}
Sorry this is a new answer to an old question, but this can be done more efficiently with a map. What you're after is random selection rather than non-repeating random. Non-repeating random is nonsensical.
Where _a is the collection, and r is not part of the collection, we lambda the random value r:
function aRandom(f){
var r = Math.random();
aRandom._a[r] ? aRandom(f) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
aRandom(function(r){ console.log(r) });
Redefine aRandom._a when the browser gets sluggish. To avoid eventual sluggishness, one should really use an UUID generation algo with sufficient entropy so that chances of repeat are effectively zero, rather than brute forcing differentiability. I chose the function name aRandom because latin prefix A- means "away from." Since the more it's used, the further away from random the output. The function produces one million unique values in 2100 ms on a Macbook.
Advantage of the above solution is no need to limit the set. As well, multiple callers can use it at the same time and assume their values are different from all other callers. This is handy for such things as noise jittering distributions with insured no overlaps.
However, it can be modified to return integers as well, so as to restrict ram use to the length supplied:
function aRandom(f,c){
var r = Math.floor(Math.random()*c);
aRandom._a[r] ? aRandom(f,c) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
var len = 10;
var resultset = [];
for(var i =0; i< len; i++){
aRandom(function(r){ resultset.push(r); }, len);
}
console.log(resultset);
randojs.com makes this a simple one-liner:
randoSequence(1, 10)
This will return an array of numbers from 1 through 10 in random order.
You just need to add the following to the head of your html document, and you can do pretty much whatever you want with randomness easily. Random values from arrays, random jquery elements, random properties from objects, and even preventing repetitions as I've shown here.
<script src="https://randojs.com/1.0.0.js"></script>
Just one solution for reference
const fiveNums = () => {
const ranNum = () => Math.floor(Math.random() * (10 + 1));
let current;
let arr = [];
while(arr.length < 5) {
if(arr.indexOf(current = ranNum()) === -1) {
arr.push(current);
}
}
return arr;
};
fiveNums();
In case no permutation is wanted and/or length shall be variable, here is a solution for non repeating randomized lists/arrays without if-statements:
Shuffle function:
Input:
Array or object(list) of arbitrary length
optional: last key to be filtered (Array: index number, List: String of key)
Output:
random Key
to get your random item use myArrayOrList[key]
// no repeat if old_key is provided
function myShuffle(arr_or_list, old_key = false) {
var keys = Array.from(Object.keys(arr_or_list)); //extracts keys
if (old_key != false) {
keys.splice(keys.indexOf(old_key), 1); // removes old_key from keys
};
var randomKey = keys[Math.floor(Math.random() * keys.length)]; // get random key
return randomKey;
}
//test:
const a = [10, 20, 30, 40, 50, 60];
const b = {
"a": 10,
"bla-bla bla": 20,
"d": 30,
"c": 40
};
var oldKeys_a = [];
var oldKeys_b = [];
oldKeys_a[0] = myShuffle(a);
oldKeys_b[0] = myShuffle(b);
var i;
for (i = 1; i < 10; i++) {
oldKeys_a[i] = myShuffle(a, oldKeys_a[i - 1]);
oldKeys_b[i] = myShuffle(b, oldKeys_b[i - 1]);
}
alert('oldKeys_a: ' + oldKeys_a + '; oldKeys_b: ' + oldKeys_b)
//random...
//>>> oldKeys_a: 1,3,0,0,5,0,4,5,2,3; oldKeys_b: d,a,d,bla-bla bla,a,c,d,bla-bla bla,a,d <<<
Non-repeating range random number generation with the recursive patterns.
const getRandom = (max, memo) => {
if (max != memo.length) {
const pos = Math.floor(Math.random() * max);
if (memo.includes(pos)) {
return getRandom(max, memo);
} else {
return pos;
}
}
}
const random = [];
const range = 6;
for (let index = 0; index < range; index++) {
random.push(getRandom(range, random))
}
console.log('random', random) // random (6) [5, 3, 0, 2, 1, 4]
function getRandomNumberNoRepeat(length){
let numberPick = [0,1,2,3,4,5,6,7,8,9]
return numberPick.sort(() => Math.random() -0.5).slice(0, length)}
console.log(getRandomNumberNoRepeat(3));
let display = document.getElementById("container");
let myArray = [];
let randomiser = (min, max, vals) => {
while (myArray.length < vals) {
let randNum = Math.floor(Math.random() * (max - min + 1) + min);
if (!myArray.includes(randNum)) {
myArray.push(randNum);
}
}
return (display.textContent = myArray.join(" - "));
};
randomiser(1, 35, 7);
Here is one where you can specify how many number you need.
I decided to write this code and make a chrome extension for it to use when playing the lotto. haha. Just a learning experience for me and thanks to all who contributed. I read all posts and I'm better of today than I was yesterday in understanding shuffle and random non repeating numbers.
You don't really want a lost of random numbers. Truly random numbers must be able to repeat.
Truly random number are like throwing dice. Any number can come up next.
Shuffled numbers are like drawing playing cards. Each number can come up only once.
What you are really asking for is to shuffle a list of numbers and then use the first so many numbers from the shuffled list.
Think of making a list of numbers in order, and then using the random number generator to randomly select a number from a copy of that list. Each time, put the selected number at the end of your new list and remove it from the copy of the old list, shortening that list. When you are done, the new list will contain the shuffled numbers and the copy of the old list will be empty.
Alternately, you can take the number selected and use it immediately, shortening the copy of the list by removing the used number. Because you have removed the number from the list, it can't come up again.

Get Random unique variable num non-repeating previous or next In javascript [duplicate]

I have the following function
function randomNum(max, used){
newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
console.log(newNum + " is not in array");
return newNum;
}else{
return randomNum(max,used);
}
}
Basically I am creating a random number between 1 - 10 and checking to see if that number has already been created, by adding it to an array and checking the new created number against it. I call it by adding it to a variable..
UPDATED:
for(var i=0;i < 10;i++){
randNum = randomNum(10, usedNums);
usedNums.push(randNum);
//do something with ranNum
}
This works, but in Chrome I get the following error:
Uncaught RangeError: Maximum call stack size exceeded
Which I guess it's because I am calling the function inside itself too many times. Which means my code is no good.
Can someone help me with the logic? what's a best way to make sure my numbers are not repeating?
If I understand right then you're just looking for a permutation (i.e. the numbers randomised with no repeats) of the numbers 1-10?
Maybe try generating a randomised list of those numbers, once, at the start, and then just working your way through those?
This will calculate a random permutation of the numbers in nums:
var nums = [1,2,3,4,5,6,7,8,9,10],
ranNums = [],
i = nums.length,
j = 0;
while (i--) {
j = Math.floor(Math.random() * (i+1));
ranNums.push(nums[j]);
nums.splice(j,1);
}
So, for example, if you were looking for random numbers between 1 - 20 that were also even, then you could use:
nums = [2,4,6,8,10,12,14,16,18,20];
Then just read through ranNums in order to recall the random numbers.
This runs no risk of it taking increasingly longer to find unused numbers, as you were finding in your approach.
EDIT: After reading this and running a test on jsperf, it seems like a much better way of doing this is a Fisher–Yates Shuffle:
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
Basically, it's more efficient by avoiding the use of 'expensive' array operations.
BONUS EDIT: Another possibility is using generators (assuming you have support):
function* shuffle(array) {
var i = array.length;
while (i--) {
yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
}
}
Then to use:
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
ranNums.next().value; // first random number from array
ranNums.next().value; // second random number from array
ranNums.next().value; // etc.
where ranNums.next().value will eventually evaluate to undefined once you've run through all the elements in the shuffled array.
Overall this won't be as efficient as the Fisher–Yates Shuffle because you're still splice-ing an array. But the difference is that you're now doing that work only when you need it rather than doing it all upfront, so depending upon your use case, this might be better.
//random number without repetition in JavaScript, Just in one line;
//it can be used as _id;
//it not need to store or check;
const myRnId = () => parseInt(Date.now() * Math.random());
console.log(myRnId()); // any random number included timeStamp;
function Myrand(max,min){
arr=[];
for (i = 0; i < max; i++) {
x = Math.floor( Math.random() * max) + min;
if(arr.includes(x) == true){
i=i-1;
}else{
if(x>max==false){
arr.push(x);
}
}
}
return arr;
}
console.log(Myrand(5,1));
Try this:
var numbers = []; // new empty array
var min, max, r, n, p;
min = 1;
max = 50;
r = 5; // how many numbers you want to extract
for (let i = 0; i < r; i++) {
do {
n = Math.floor(Math.random() * (max - min + 1)) + min;
p = numbers.includes(n);
if(!p){
numbers.push(n);
}
}
while(p);
}
console.log(numbers.join(" - "));
let arr = [];
do {
let num = Math.floor(Math.random() * 10 + 1);
arr.push(num);
arr = arr.filter((item, index) => {
return arr.indexOf(item) === index
});
} while (arr.length < 10);
console.log(arr);
HTML
<p id="array_number" style="font-size: 25px; text-align: center;"></p>
JS
var min = 1;
var max = 90;
var stop = 6; //Number of numbers to extract
var numbers = [];
for (let i = 0; i < stop; i++) {
var n = Math.floor(Math.random() * max) + min;
var check = numbers.includes(n);
if(check === false) {
numbers.push(n);
} else {
while(check === true){
n = Math.floor(Math.random() * max) + min;
check = numbers.includes(n);
if(check === false){
numbers.push(n);
}
}
}
}
sort();
//Sort the array in ascending order
function sort() {
numbers.sort(function(a, b){return a-b});
document.getElementById("array_number").innerHTML = numbers.join(" - ");
}
DEMO
The issue is that as you approach saturation you begin to take longer and longer to generate a unique number "randomly". For instance, in the example you provided above the max is 10. Once the used number array contains 8 numbers it can potentially take a long time for the 9th and 10th to be found. This is probably where the maximum call stack error is being generated.
jsFiddle Demo showing iteration count being maxed
By iterating inside of your recursion, you can see that a large amount of execution occurs when the array is completely saturated, but the function is called. In this scenario, the function should exit.
jsFiddle Demo with early break
if( used.length >= max ) return undefined;
And one last way to accomplish both the iteration checks and the infinite recursion would be like this jsFiddle Demo:
function randomNum(max, used, calls){
if( calls == void 0 ) calls = 0;
if( calls++ > 10000 ) return undefined;
if( used.length >= max ) return undefined;
var newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
return newNum;
}else{
return randomNum(max,used,calls);
}
}
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Math.random()</h2>
<p>Math.random() returns a random number between 0 (included) and 1 (excluded):</p>
<p id="demo"></p>
<script>
var storeArray = []
function callRamdom(){
var randomNumber = Math.floor(Math.random() * 5);
return randomNumber;
}
function randomStore(){
var localValue = callRamdom()
var status = false;
for(i=0;i<5; i++){
var aa = storeArray[i];
if(aa!=localValue){
console.log(storeArray[i]+"hhhhh"+ localValue);
if(i==4){
status=true;
}
}
else
break;
}
if(status==true){
storeArray.push(localValue);
}
if(storeArray.length!=5){
randomStore();
}
return storeArray;
}
document.getElementById("demo").innerHTML = randomStore();
</script>
</body>
</html>
while(randArr.length < SIZEOFARRAY){
val = Math.floor((Math.random() * RANGEOFVALUES));
if(randArr.indexOf(val) < 0){
randArr.push(val);
}
}
You can change SIZEOFARRAY to the size of the array you wish to use
and also change RANGEOFVALUES to the range of values you wish to randomize
const GenerateRandomNumbers = (max) => {
let orderNumbers = new Set();
for (let i = 1; ;i++){
let random = Math.floor(Math.random() * max + 1) ;
orderNumbers.add(random);
if (orderNumbers.size == max){
break;
}
}
return orderNumbers;}
function randomNumbers(max) {
function range(upTo) {
var result = [];
for(var i = 0; i < upTo; i++) result.push(i);
return result;
}
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
var myArr = shuffle(range(max));
return function() {
return myArr.shift();
};
}
Built a little test, try this on jsfiddle:
var randoms = randomNumbers(10),
rand = randoms(),
result = [];
while(rand != null) {
result.push(rand);
rand = randoms();
}
console.log(result);
Shuffle function courtesy of dzone.com.
This is how I achieve it using underscore.js
To get n integers from min to max values. Where n is the size argument.
var randomNonRepeatingIntFromInterval = function(min, max, size) {
var values = [];
while (values.length < size) {
values.push(Math.floor(Math.random() * ( max - min + 1) + min));
values = _.uniq(values);
}
return values;
}
Sorry this is a new answer to an old question, but this can be done more efficiently with a map. What you're after is random selection rather than non-repeating random. Non-repeating random is nonsensical.
Where _a is the collection, and r is not part of the collection, we lambda the random value r:
function aRandom(f){
var r = Math.random();
aRandom._a[r] ? aRandom(f) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
aRandom(function(r){ console.log(r) });
Redefine aRandom._a when the browser gets sluggish. To avoid eventual sluggishness, one should really use an UUID generation algo with sufficient entropy so that chances of repeat are effectively zero, rather than brute forcing differentiability. I chose the function name aRandom because latin prefix A- means "away from." Since the more it's used, the further away from random the output. The function produces one million unique values in 2100 ms on a Macbook.
Advantage of the above solution is no need to limit the set. As well, multiple callers can use it at the same time and assume their values are different from all other callers. This is handy for such things as noise jittering distributions with insured no overlaps.
However, it can be modified to return integers as well, so as to restrict ram use to the length supplied:
function aRandom(f,c){
var r = Math.floor(Math.random()*c);
aRandom._a[r] ? aRandom(f,c) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
var len = 10;
var resultset = [];
for(var i =0; i< len; i++){
aRandom(function(r){ resultset.push(r); }, len);
}
console.log(resultset);
randojs.com makes this a simple one-liner:
randoSequence(1, 10)
This will return an array of numbers from 1 through 10 in random order.
You just need to add the following to the head of your html document, and you can do pretty much whatever you want with randomness easily. Random values from arrays, random jquery elements, random properties from objects, and even preventing repetitions as I've shown here.
<script src="https://randojs.com/1.0.0.js"></script>
Just one solution for reference
const fiveNums = () => {
const ranNum = () => Math.floor(Math.random() * (10 + 1));
let current;
let arr = [];
while(arr.length < 5) {
if(arr.indexOf(current = ranNum()) === -1) {
arr.push(current);
}
}
return arr;
};
fiveNums();
In case no permutation is wanted and/or length shall be variable, here is a solution for non repeating randomized lists/arrays without if-statements:
Shuffle function:
Input:
Array or object(list) of arbitrary length
optional: last key to be filtered (Array: index number, List: String of key)
Output:
random Key
to get your random item use myArrayOrList[key]
// no repeat if old_key is provided
function myShuffle(arr_or_list, old_key = false) {
var keys = Array.from(Object.keys(arr_or_list)); //extracts keys
if (old_key != false) {
keys.splice(keys.indexOf(old_key), 1); // removes old_key from keys
};
var randomKey = keys[Math.floor(Math.random() * keys.length)]; // get random key
return randomKey;
}
//test:
const a = [10, 20, 30, 40, 50, 60];
const b = {
"a": 10,
"bla-bla bla": 20,
"d": 30,
"c": 40
};
var oldKeys_a = [];
var oldKeys_b = [];
oldKeys_a[0] = myShuffle(a);
oldKeys_b[0] = myShuffle(b);
var i;
for (i = 1; i < 10; i++) {
oldKeys_a[i] = myShuffle(a, oldKeys_a[i - 1]);
oldKeys_b[i] = myShuffle(b, oldKeys_b[i - 1]);
}
alert('oldKeys_a: ' + oldKeys_a + '; oldKeys_b: ' + oldKeys_b)
//random...
//>>> oldKeys_a: 1,3,0,0,5,0,4,5,2,3; oldKeys_b: d,a,d,bla-bla bla,a,c,d,bla-bla bla,a,d <<<
Non-repeating range random number generation with the recursive patterns.
const getRandom = (max, memo) => {
if (max != memo.length) {
const pos = Math.floor(Math.random() * max);
if (memo.includes(pos)) {
return getRandom(max, memo);
} else {
return pos;
}
}
}
const random = [];
const range = 6;
for (let index = 0; index < range; index++) {
random.push(getRandom(range, random))
}
console.log('random', random) // random (6) [5, 3, 0, 2, 1, 4]
function getRandomNumberNoRepeat(length){
let numberPick = [0,1,2,3,4,5,6,7,8,9]
return numberPick.sort(() => Math.random() -0.5).slice(0, length)}
console.log(getRandomNumberNoRepeat(3));
let display = document.getElementById("container");
let myArray = [];
let randomiser = (min, max, vals) => {
while (myArray.length < vals) {
let randNum = Math.floor(Math.random() * (max - min + 1) + min);
if (!myArray.includes(randNum)) {
myArray.push(randNum);
}
}
return (display.textContent = myArray.join(" - "));
};
randomiser(1, 35, 7);
Here is one where you can specify how many number you need.
I decided to write this code and make a chrome extension for it to use when playing the lotto. haha. Just a learning experience for me and thanks to all who contributed. I read all posts and I'm better of today than I was yesterday in understanding shuffle and random non repeating numbers.
You don't really want a lost of random numbers. Truly random numbers must be able to repeat.
Truly random number are like throwing dice. Any number can come up next.
Shuffled numbers are like drawing playing cards. Each number can come up only once.
What you are really asking for is to shuffle a list of numbers and then use the first so many numbers from the shuffled list.
Think of making a list of numbers in order, and then using the random number generator to randomly select a number from a copy of that list. Each time, put the selected number at the end of your new list and remove it from the copy of the old list, shortening that list. When you are done, the new list will contain the shuffled numbers and the copy of the old list will be empty.
Alternately, you can take the number selected and use it immediately, shortening the copy of the list by removing the used number. Because you have removed the number from the list, it can't come up again.

Fastest way to generate a lot of unique small random numbers in JavaScript

Wondering how to quickly generate lots of unique, small random numbers. When I implemented it like this it slows down exponentially it seems like, to the point where it never finishes, or will take hours to complete. Probably because it creates tons of duplicates toward the end.
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) i++
else {
intsmap[int] = true
intsarray.push(int)
}
}
// return intsarray
function randominteger(exp) {
var string = rand(exp)
return pad(string, exp)
}
function pad(num, size) {
var s = rand(9) + num
return s.substr(s.length - size)
}
function rand(exp) {
var integer = Math.random() * Math.pow(10, exp) << 0
var string = toString(integer, '0123456789')
return string
}
function toString(value, code) {
var digit
var radix = code.length
var result = ''
do {
digit = value % radix
result = code[digit] + result
value = Math.floor(value / radix)
} while (value)
return result
}
Wondering how to accomplish that but the code works within a few seconds if possible.
Update
I would like for the set of numbers to be distributed evenly over an arbitrary range (in this example 1000000 strings, not necessarily from 0-1000000, eg maybe 5050000 is in there).
I would like for the numbers to not necessarily be valid numbers, just a string of integers. So for example they can include 01010101 as a valid string, even though that's not a valid number.
You can use an object as a look up and only insert unique random number
var intsmap = {};
var i = 100000;
while (i--) {
var int = Math.random() * Math.pow(10, 6) << 0;
if(intsmap[int])
continue;
else
intsmap[int] = true;
}
console.log(Object.keys(intsmap));
You can use also use Durstenfeld shuffle after generating number in the given range.
var arr = Array.from({length:1000000}, (_,i) => (i+1));
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
shuffleArray(arr);
console.log(arr);
Just try to shuffle the array of numbers 1 to maxNum
First create an array
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e,i)=>i+1);
Now shuffle the array
arr.sort(function() {
return .5 - Math.random();
});
Now you have the array of unique random numbers
Demo
var startTime = new Date().getTime();
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e, i) => i + 1);
arr.sort(function() {
return .5 - Math.random();
});
var endTime = new Date().getTime();
console.log( "Time taken to get " + maxNum + " size random unique number is " + ( endTime - startTime ) + " ms");
I can propose this approach:
generate a random number
cast it to a string (0.1234567812345678)
and extract 6 substrings of length of 10
Code:
var res = {},
s = "";
for (let i=0; i<1000000; ++i) {
s = Math.random().toString();
for (let j=0; j<6; ++j) {
res[s.substring(2+j, 12+j)] = true; // extract 10 digits
}
}
After 1,000,000 iterations, you have computed 6,000,000 numbers with very little collisions (1,800 in average). So you have your 1,000,000 numbers and more in few seconds.
If you need unique big array try to think in other way. Just create range 0 ... 100000 and shuffle it and apply you function that you need for this array.
var acc = 0;
const result = [];
for(var i = 0; i < 100000; i++)
result.push(acc += Math.floor(Math.random() * 10) + 1);
I think the most expensive operation is the hashtable lookup/insertion, so simply do it without it.
One place where you might loose performances is in the Math.random call.
It's a quite expensive call, and you are calling it a huge number of times to generate your strings.
One solution to leverage it is to grab the whole string from a single result of Math.random().
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) {
i++
} else {
intsmap[int] = true
intsarray.push(int)
}
}
console.log(intsarray);
// It takes the whole string from a single call to 'random'.
// The maximum length is 16.
function randominteger(length){
return (Math.random() + '').substr(2,length);
}

Unique random number generation using javascript

I use the following code for generating the random number from 0 to 15. I use a function random() for generating the unique number i call the function like this
cat=random();
I save the random number with in the array r[]. and check the newly generating number is in the array or not. If the duplicate occurs i call the random() function once again. I use alert for just check it correctly working or not
function random(){
var ran,max=0,min=0;
max=r.length;
alert(max);
if (max>15)
alert("no more space");
ran=Math.floor(Math.random() * 15) + 0;
for (i=0;i<max;i++)
if (ran==r[i])
min++;
if (min>0){
alert("calling");
random(); //return in here
}else{
i=parseInt(max);
r[i]=ran;
return(ran);
alert(ran);
}
}
But the variable return within the function when the duplication occurs can anybody help with this.
I'd create an array and shuffle it using Fisher-Yates.
function shuffle(arr) {
var shuffled = arr.slice(0), i = arr.length, temp, index;
while (i--) {
index = Math.floor(i * Math.random());
temp = shuffled[index];
shuffled[index] = shuffled[i];
shuffled[i] = temp;
}
return shuffled;
}
// Create the array
var i = 16, arr = [];
while (i--) arr[i] = i;
// Shuffle it
arr = shuffle(arr);
// Array is now the numbers 0-15 in a random order
console.log(arr);
Bored, quick hack job, but I believe it'll work:
// Minimum random number
var min = 0;
// Maximum random number
var max = 15;
// Returns a random number between min and max
function random() {
var random_number = Math.random();
return Math.floor((random_number * max) + min);
}
// Returns false if number is in the array
function random_is_unique(random_num_, array_) {
// Could use indexOf, but just looping here for simplicity.
// And not so sure IE has this capability.
for(i = 0; i < array_.length; i++) {
if(array_[i] == random_num_) {
return false;
}
}
return true;
}
// Returns a guaranteed unique, or -1 if no more unique values
// are availble to return
function guaranteed_unique(array_) {
random_number = random();
// Just an iterator, so we have a terminating condition
tries = 0;
while(!random_is_unique(random_number, array_)) {
// This is dumb. There's likely a better way to do this, but it's
// quick and dirty. It also does not guarantee you've tested all
// integers.
if(tries > max) {
return -1;
}
random_number = random();
tries++;
}
return random_number;
}
my_array = new Array();
my_array[0] = 1;
my_array[1] = 15;
my_array[2] = 6;
my_array[3] = 9;
my_array[4] = 13;
my_random_number = guaranteed_unique(my_array);
alert("Random number is " + my_random_number);
i modified a solution that was useful fr me
it gets rid of empty entries between numbers and fills them with unique number between 1-9
var arr = [,2,,4,,6,7,,]; //**example**<br/>
while(arr.length < 9){<br/>
var randomnumber=Math.floor(Math.random()*9+1);<br/>
var found=false;<br/>
for(var i=0;i<arr.length;i++){<br/>
if(arr[i]==randomnumber){found=true;break;}<br/>
}<br/>
if(!found)<br/>
for(k=0;k<9;k++)<br/>
{if(!arr[k]) //**if it's empty !!MODIFICATION**<br/>
{arr[k]=randomnumber; break;}}<br/>
}<br/>
alert(arr); //**outputs on the screen**<br/>

Javascript generate random unique number every time

Ok so i need to create four randomly generated numbers between 1-10 and they cannot be the same. so my thought is to add each number to an array but how can I check to see if the number is in the array, and if it is, re-generate the number and if it isnt add the new number to the array?
so basically it will go,
1.create new number and add to array
2.create second new number, check to see if it exist already, if it doesn't exist, add to array. If it does exist, re-create new number, check again etc...
3.same as above and so on.
You want what is called a 'random grab bag'. Consider you have a 'bag' of numbers, each number is only represented once in this bag. You take the numbers out, at random, for as many as you need.
The problem with some of the other solutions presented here is that they randomly generate the number, and check to see if it was already used. This will take longer and longer to complete (theoretically up to an infinite amount of time) because you are waiting for the random() function to return a value you don't already have (and it doesn't have to do that, it could give you 1-9 forever, but never return 10).
There are a lot of ways to implement a grab-bag type solution, each with varying degrees of cost (though, if done correctly, won't ever be infinite).
The most basic solution to your problem would be the following:
var grabBag = [1,2,3,4,5,6,7,8,9,10];
// randomize order of elements with a sort function that randomly returns -1/0/1
grabBag.sort(function(xx,yy){ return Math.floor(Math.random() * 3) - 1; })
function getNextRandom(){
return grabBag.shift();
};
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
This is of course destructive to the original grabBag array. And I'm not sure how 'truly random' that sort is, but for many applications it could be 'good enough'.
An slightly different approach would be to store all the unused elements in an array, randomly select an index, and then remove the element at that index. The cost here is how frequently you are creating/destroying arrays each time you remove an element.
Here are a couple versions using Matt's grabBag technique:
function getRandoms(numPicks) {
var nums = [1,2,3,4,5,6,7,8,9,10];
var selections = [];
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
You can see it work here: http://jsfiddle.net/jfriend00/b3MF3/.
And, here's a version that lets you pass in the range you want to cover:
function getRandoms(numPicks, low, high) {
var len = high - low + 1;
var nums = new Array(len);
var selections = [], i;
// initialize the array
for (i = 0; i < len; i++) {
nums[i] = i + low;
}
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
And a fiddle for that one: http://jsfiddle.net/jfriend00/UXnGB/
Use an array to see if the number has already been generated.
var randomArr = [], trackingArr = [],
targetCount = 4, currentCount = 0,
min = 1, max = 10,
rnd;
while (currentCount < targetCount) {
rnd = Math.floor(Math.random() * (max - min + 1)) + min;
if (!trackingArr[rnd]) {
trackingArr[rnd] = rnd;
randomArr[currentCount] = rnd;
currentCount += 1;
}
}
alert(randomArr); // Will contain four unique, random numbers between 1 and 10.
Working example: http://jsfiddle.net/FishBasketGordo/J4Ly7/
var a = [];
for (var i = 0; i < 5; i++) {
var r = Math.floor(Math.random()*10) + 1;
if(!(r in a))
a.push(r);
else
i--;
}
That'll do it for you. But be careful. If you make the number of random numbers generated greater than the may number (10) you'll hit an infinite loop.
I'm using a recursive function. The test function pick 6 unique value between 1 and 9.
//test(1, 9, 6);
function test(min, max, nbValue){
var result = recursValue(min, max, nbValue, []);
alert(result);
}
function recursValue(min, max, nbValue, result){
var randomNum = Math.random() * (max-min);
randomNum = Math.round(randomNum) + min;
if(!in_array(randomNum, result)){
result.push(randomNum);
nbValue--;
}
if(nbValue>0){
recursValue(min, max, nbValue, result);
}
return result;
}
function in_array(value, my_array){
for(var i=0;i< my_array.length; i++){
if(my_array[i] == value){
console.log(my_array+" val "+value);
return true;
}
}
return false;
}
Here is a recursive function what are you looking for.
"howMany" parameter is count of how many unique numbers you want to generate.
"randomize" parameter is biggest number that function can generate.
for example : rand(4,8) function returns an array that has 4 number in it, and the numbers are between 0 and 7 ( because as you know, Math.random() function generates numbers starting from zero to [given number - 1])
var array = [];
var isMatch= false;
function rand(howMany, randomize){
if( array.length < howMany){
var r = Math.floor( Math.random() * randomize );
for( var i = 0; i < howMany; i++ ){
if( array[i] !== r ){
isMatch= false;
continue;
} else {
isMatch= true;
break;
}
}
if( isMatch == false ){
array.push(r);
ran(howMany, randomize);
}
ran(howMany, randomize);
return array;
}
}
In your answer earlier, you do have a small bug. Instead of
var originalLength = grabBag.length;
for(var i = 0; i < originalLength .length; i++){
console.log(getNextRandom());
}
I believe you meant:
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
Thanks.

Categories

Resources