I have an annoying script I can't complete.
I need 32 non-repeating numbers out of a possible 0-64 number set. Every time I try to create a loop to check the new random number against all the numbers in the array I end up with nothing, or an infinite loop.
I'm stumped :(
Try this:
var keys = [], numbers = [], x, total = 0;
while(total < 32) {
x = Math.floor(Math.random() * 64);
// way faster that looping through the array to check if it exists
if(keys[x] == undefined) {
keys[x] = 1;
numbers.push(x);
total++;
}
}
console.log(numbers);
Working Demo
This code will generate a non repeating random number between 0 and whatever number you give it and will start over when it has been called the amount of the number you give it.
Give it a try:
let randomNumber = function (max) {
let min = 0, prevIndexes = [];
function exec(max2) {
max = max || max2;
let result = Math.floor(Math.random() * (max - min + 1) + min);
if (prevIndexes) {
if (prevIndexes.length - 1 === max) {
clear();
}
let foundDouble, eqPrevInn = true;
while (eqPrevInn) {
foundDouble = false;
result = Math.floor(Math.random() * (max - min + 1) + min);
for (let i = 0, l = prevIndexes.length; i < l; i++) {
if (result === prevIndexes[i]) {
foundDouble = true;
break;
}
}
if (!foundDouble) {
eqPrevInn = false;
}
}
}
prevIndexes.push(result);
console.log(prevIndexes);
return result;
}
let clear = function () {
if (prevIndexes) {
prevIndexes = [];
// console.log('prevIndexes has been cleared');
}
else {
// console.log('already clear');
}
}
return {
exec: exec,
clear: clear
}
};
let random32 = randomNumber(32/*range*/).exec;
for (let i = 0; i <= 32; i++) {
random32();
}
Related
so i already make a code to check if the string palindrom or not
let randomNumber = '13431'
let b = ''
//to check palindrom or not
for (i = randomNumber.length-1 ; i >= 0 ; i--) {
b = b + randomNumber[i]
}
if (randomNumber === b) {
console.log('palindrom')
} else {
console.log('not')
}
but i want to make the randomNumber is really random using loops (from x to y), like this
for (let i = 12 ; i < 30 ; i++) {
console.log(i)
}
so i'll generate random number from 12 -> 30 but ends in '22' using break; bcs it's palindrom
It will generate random number and check if the number is palindrome:
function isPalindrome (str) {
return str.split('').reverse().join('') == str;
}
start = Math.floor(Math.random() * 100); // your case 12
end = Math.floor(Math.random() * 100); // your case 30
for (i = start; i <= end; i++) {
if (isPalindrome(i.toString())) {
console.log(`Number ${i} is palindrome`);
break;
}
}
you can do something like this
//generate an array from start to stop
const generateRangeNumbers = (start, stop) => Array.from({length: stop - start + 1}).map((_, i) => start + i)
//this checks if the number is palindrome
const isPalindrome = n => n.toString().split('').reverse().join('') === n.toString()
//this returns an array of palindrome in the range
const result = generateRangeNumbers(12, 30).filter(isPalindrome)
//if you need just the first match you can use find instead of filter
const result2 = generateRangeNumbers(12, 30).find(isPalindrome)
console.log(result, result2)
you can do it with loops in this way
let result
for (let i = 12; i <= 30; i++) {
if (i.toString() === i.toString().split('').reverse().join('')) {
result = i
break;
}
}
console.log(result)
I am trying to choose random unique numbers everytime when I click button. For this my function is:
const chooseNumber = () => {
var r = Math.floor(Math.random() * 75) + 1;
console.log(r)
while(selectedNumbers.indexOf(r) === -1) {
selectedNumbers.push(r);
}
console.log(selectedNumbers);
};
But the problem is if the random number is already on my list, I need to click the button again to generate new number and it goes until it find the number which is not on the list. But I want to generate number which is not on the list directly so I dont need to click the button everytime. Thanks for you helps.
You are in a right track, except the while loop should be for random number generator, not pushing number into an array:
const selectedNumbers = [];
const chooseNumber = () => {
let r;
do
{
r = Math.floor(Math.random() * 75) + 1;
}
while(selectedNumbers.indexOf(r) > -1)
selectedNumbers.push(r);
console.log(r, "["+selectedNumbers+"]");
};
<button onclick="chooseNumber()">Generate</button>
Note, that this might eventually lead to a freeze, since there is no fail safe check if array is full, so to battle that we should also check length of the array:
const selectedNumbers = [];
const maxNumber = 75;
const chooseNumber = () => {
let r;
do
{
r = ~~(Math.random() * maxNumber) + 1;
}
while(selectedNumbers.indexOf(r) > -1 && selectedNumbers.length < maxNumber)
if (selectedNumbers.length < maxNumber)
selectedNumbers.push(r);
else
console.log("array is full");
console.log(r, "["+selectedNumbers+"]");
};
for(let i = 0; i < 76; i++)
{
chooseNumber();
}
<button onclick="chooseNumber()">Generate</button>
Don't rely on a loop to generate a unique (unseen) integer in a limited range.
First, once all of the values in the range have been exhausted there will be no possibilities left, so you'll be left in an endless loop on the next invocation.
Second, it's wasteful of the processor because you are generating useless values on each invocation.
Instead, generate all of the values in range in advance (once), then shuffle them and get the last one from the array on each invocation (and throw an error when none remain):
/**
* Durstenfeld shuffle
*
* - https://stackoverflow.com/a/12646864/438273
* - https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
*/
function shuffleArray (array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
/** Get shuffled array of all integers in range */
function generateShuffledIntegerArray (min, max) {
const arr = [];
for (let i = min; i <= max; i += 1) arr.push(i);
shuffleArray(arr);
return arr;
}
const getUniqueInt = (() => {
const numbers = generateShuffledIntegerArray(1, 75);
return () => {
const n = numbers.pop();
if (typeof n === 'number') return n;
throw new Error('No unique numbers remaining');
};
})();
// Will log 75 integers, then throw on the 76th invocation:
for (let i = 1; i <= 76; i += 1) {
const n = getUniqueInt();
console.log(`${i}:`, n);
}
Code in TypeScript Playground
Your while loop is unnecessary. You could use an "if" statement instead.
To avoid clicking again on your button, you can do a recursive function like:
const chooseNumber = () => {
var r = Math.floor(Math.random() * 75) + 1;
console.log(r)
if(selectedNumbers.indexOf(r) === -1) {
selectedNumbers.push(r);
console.log(selectedNumbers);
} else {
chooseNumber();
}
};
I'm working on a project for school. I need to generate an array of 15 random integers between 1 & 50. I have a function, but I would not like for the numbers to repeat. (for example, if the number 3 is located at index 0, I would not like for it to show up again in the array.) If I could get some help on not getting repeat numbers, that would be great.
Thank you for any help!
var arr;
function genArray() {
//generates random array
arr = [];
for (var i = 0; i < 15; i++) {
var min = 1;
var max = 50;
var arrayValue = Math.floor(Math.random() * (max - min + 1)) + min;
arr.push(arrayValue);
}
arr.sort(function(a, b) {
return a - b
});
console.log(arr);
}
In the loop generate a new random number while the number is in the array. In other words only continue when the new number is not in the array already.
var arr;
function genArray() {
//generates random array
arr = [];
for (var i = 0; i < 15; i++) {
var min = 1;
var max = 50;
do
{
var arrayValue = Math.floor(Math.random() * (max - min + 1)) + min;
}while(arr.includes(arrayValue))
arr.push(arrayValue);
}
arr.sort(function(a, b) {
return a - b
});
console.log(arr);
}
genArray();
You can make a function in which check the number if its already in array than regenrate the number else push the number in array
var arr;
function genArray() {
//generates random array
arr = [];
for (var i = 0; i < 15; i++) {
var min = 1;
var max = 50;
var arrayValue = Math.floor(Math.random() * max) + min;
if(checkno(arrayValue)==true)
arr.push(arrayValue);
}
arr.sort(function(a, b) {
return a - b
});
console.log(arr);
}
function checkno(var no)
{
for(var i=0;i<arr.length;i++)
{
if(arr[i]==no)
return false;
else
return true;
}
}
An alternate solution involves the Set object, sets only have unique elements, multiple elements of the same value are ignored.
Example of the set object implemented for this use:
var temp = new Set();
while (temp.size < 15) {
var min = 1;
var max = 50;
temp.add(Math.floor(Math.random()*(max-min+1))+min);
}
This approach uses Arrow functions, forEach and includes functions.
let LENGTH = 15;
let numbers = new Array(LENGTH).fill();
let findRandomNumber = (i) => {
let rn;
while (numbers.includes((rn = Math.floor(Math.random() * 50) + 1))) {}
numbers[i] = rn;
};
numbers.forEach((_, i) => findRandomNumber(i));
console.log(numbers.sort((a, b) => a - b));
.as-console-wrapper {
max-height: 100% !important
}
You do not need to check the resulting array and regenerate the number. It is not efficient.
Please take a look at the following snippet:
function get_N_rand(N = 15, min = 1, max = 50) { // set default values
var N_rand = [], range = [];
for (var i = min; i <= max;) range.push(i++); // make array [min..max]
while (N_rand.length < N) { // cut element from [min..max] and put it into result
var rand_idx = ~~(Math.random() * range.length);
N_rand.push(range.splice(rand_idx, 1)[0]);
}
return N_rand;
}
console.log(JSON.stringify( get_N_rand() )); // run with defaults
console.log(JSON.stringify( get_N_rand(6, 10, 80) )); // run with arbitraries
so I know this questing has been asked, but all the answers that were given are already known to me. I don't want to make a variable of all the posible numbers (that was always the answer). So to go to the question, I want to make a random number generator, that will generate me 7 numbers, that must not be the same. For example, I get random numbers:
"5,16,12,5,21,37,2" ... But I don't want the number 5 to be used again, so I want different numbers. I made a code for the generation, but I can not think of any good method/way to do this. I was thinking that maybe check if the number is already in array and if it is, then generate another number, but as I'm amateur in JavaScript, I don't know how to do this. So here is my JavaScript code:
// JavaScript Document
function TableOn()
{
document.write("<table border='1'>");
}
function TableOff()
{
document.write("</table>");
}
function RandNum()
{
var n = new Array();
for(var i=0;i<7;i++)
{
n[i] = Math.round((1+(Math.random()*40)));
}
TableOn();
for(var c=0;c<7;c=c+1)
{
document.write("<tr><td>"+n[c]+"</td></tr>");
}
TableOff();
}
In HTML I just have a button, that is onclick="RandNum()" ... Pardon for my English.
I would do it like this:
var nums = [], numsLen = 5, maxNum = 100, num;
while (nums.length < numsLen) {
num = Math.round(Math.random() * maxNum);
if (nums.indexOf(num) === -1) {
nums.push(num);
}
}
This generates an array with 5 random numbers in the range 0..100.
(numsLen cannot be greater than maxNum.)
These commands can be used to check if a value is/is not in your array:
if ( !!~n.indexOf(someVal) ) {
// someVal is in array "n"
}
if ( !~n.indexOf(someVal) ) {
// someVal is not in array "n"
}
I'd use a string, storing the generated random numbers with a divider. Then check if the newly generated number is in that string.
Something like this
generated = "";
for(var i=0;i<7;i++)
{
generate = Math.round((1+(Math.random()*40))); //generate = 5
while (generated.indexOf("[" + generate + "]") != -1) { //checking if the [5] is already in the generated string, and loop until it's a different number
generate = Math.round((1+(Math.random()*40))); //get a new random number
}
generated += "[" + generate + "]";
n[i] = generate;
}
or you can take another longer approach
for(var i=0;i<7;i++)
{
repeated = true;
while (repeated) {
repeated = false;
generate = Math.round((1+(Math.random()*40)));
for (var a=0; a < i, a++) {
if (generate == n[a]) { repeated = true; }
}
}
n[i] = generate;
}
Here's a function to generate an array of n unrepeated random numbers in [min, max):
function rands(n, min, max) {
var range = max - min;
if (range < n)
throw new RangeError("Specified number range smaller than count requested");
function shuffle() {
var deck = [], p, t;
for (var i = 0; i < range; ++i)
deck[i] = i + min;
for (i = range - 1; i > 0; --i) {
p = Math.floor(Math.random() * i);
t = deck[i];
deck[i] = deck[p];
deck[p] = t;
}
return deck.slice(0, n);
}
function find() {
var used = {}, rv = [], r;
while (rv.length < n) {
r = Math.floor(Math.random() * range + min);
if (!used[r]) {
used[r] = true;
rv.push(r);
}
}
return rv;
}
return range < 3 * n ? shuffle() : find();
}
This code checks the range of possible values and compares it to the number of random values requested. If the range is less than three times the number of values requested, the code uses the shuffle to avoid the terrible performance of the lookup approach. If the range is large, however, the lookup approach is used instead.
Not sure if OP's requirement of non-repeating is really needed, but here's a fiddle of something that could work if your number range isn't too big:
http://jsfiddle.net/6rEDV/1/
function range(start, end, step) {
if (typeof step === 'undefined') {
step = 1;
}
if (typeof start === 'undefined' || typeof end === 'undefined') {
throw TypeError('Must have start and end');
}
var ret = [];
for (var i = start; i <= end; i += step) {
ret.push(i);
}
return ret;
};
// source: http://stackoverflow.com/a/6274381/520857
function shuffle(o) { //v1.0
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;
};
function getNonRepeatingRand(min, max, num) {
var arr = shuffle(range(min, max));
return arr.slice(0, num-1);
}
// Get 7 random numbers between and including 1 and 1000 that will *not* repeat
console.log(getNonRepeatingRand(1,1000,7));
A possibly slower, but less memory intensive method:
http://jsfiddle.net/Qnd8Q/
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getNonRepeatingRand(min, max, num) {
var ret = [];
for (var i = 0; i < num; i++) {
var n = rand(min, max);
if (ret.indexOf(n) == -1) {
ret.push(n);
} else {
i--;
}
}
return ret;
}
console.log(getNonRepeatingRand(1,5,5));
var n = new Array(),num;
function TableOn()
{
document.write("<table border='1'>");
}
function TableOff()
{
document.write("</table>");
}
function check_repition()
{
num=Math.round((1+(Math.random()*40)))
if(n.indexOf(num)==-1)
return true;
else
return false;
}
function RandNum()
{
for(var i=0;i<7;i++)
{
if(check_repition())
n[i] =num;
else // keep checking
{
check_repition()
n[i] =num;
}
}
TableOn();
for(var c=0;c<7;c=c+1)
{
document.write("<tr><td>"+n[c]+"</td></tr>");
}
TableOff();
}
RandNum()
I'm trying to make a bingo game for fun. I've looked in a lot of places for a unique generator but I can't seem to find one. I've tried to make my own,but once it actually hits a number that's the same it does an infinite loop. I've tried a simple code that in theory should work but for some reason things pass through. What can I do!?
var bc = [];
for (var i = 0; i < 5; i++) {
var r = Math.floor(Math.random()*20+1) + 0;
if(!(r in bc)){
bc.push(r);
}
else
{
i--;
}
}
____________________________________________
____________________________________________
____________________________________________
b1=0;
b2=0;
b3=0;
b4=0;
b5=0;
var bc = [b1,b2,b3,b4,b5]
var bnc = function(){
var n = Math.floor(Math.random() * 5+1)+0;
var n2 = Math.floor(Math.random() * 5+1)+0;
b1 = n;
var a1 = true;
var as = false;
while(a1){
var c = n;
if(c===b1||c===0 ||as!==false){
c = n2;
as=true;
}
if(c===b1||c===0&&as===true){
c = n;
as=false;
}
if(c!=b1){
b2 = c;
a1 = false;
a2 = true;
}
}
};
bnc();
console.log("new1");
console.log(b1,b2,b3,b4,b5);
//_______________________________________
var bnc2 = function(){
var n = Math.floor(Math.random() * 5+1)+0;
var n2 = Math.floor(Math.random() * 5+1)+0;
var a1 = true;
var as = false;
while(a1){
var c = n;
if(c===b1||c===b2||c===0&&as===false){
c = n2;
as=true;
}
if(c===b1||c===b2||c===0&&as===true){
c = n;
as=false;
}
if(c!=b1&&c!=b2){
b3 = c;
console.log("made it 1");
a1 = false;
}
}
};
bnc2();
console.log("new2");
console.log(b1,b2,b3,b4,b5);
once it actually hits a number that's the same
It never should. Such algorithms take longer the longer they run. You should take a different approach:
Put all possible numbers into a pool. Once you draw a number, remove it from the pool. Just like it's done in real life.
var pool = [1, 2, 3, 4, 5];
var getNumber = function () {
if (pool.length == 0) {
throw "No numbers left";
}
var index = Math.floor(pool.length * Math.random());
var drawn = pool.splice(index, 1);
return drawn[0];
};
I would rather do it with something like this:
http://jsfiddle.net/YC58s/
generate = function(length)
{
var arr = [];
var n;
for(var i=0; i<length; i++)
{
do
n = Math.floor(Math.random()*20+1);
while(arr.indexOf(n) !== -1)
arr[i] = n;
}
return arr;
}
This can handle generating upto 20 digit UNIQUE random number
JS
var generatedNumbers = [];
function generateRandomNumber(precision) { // precision --> number precision in integer
if (precision <= 20) {
var randomNum = Math.round(Math.random().toFixed(precision) * Math.pow(10, precision));
if (generatedNumbers.indexOf(randomNum) > -1) {
if (generatedNumbers.length == Math.pow(10, precision))
return "Generated all values with this precision";
return generateRandomNumber(precision);
} else {
generatedNumbers.push(randomNum);
return randomNum;
}
} else
return "Number Precision shoould not exceed 20";
}
generateRandomNumber(1);
JsFiddle
window.onload = unRanNumGen(20, 1, 12);
//above, we need 12 random numbers between 20 (included) and 1(included)
function unRanNumGen(max, min, limit){
//max = maximum number [inclued] (range of numbers)
//min = minimum number [included] (range of numbers)
//limit = number of random numbers (how many numbers do you want?)
var pool = [genRan(max, min)];
for(i=0; i<limit; i++){
for(n = 0; n <i; n++){
if(pool[n] !== genRan(max, min)){
pool.push(genRan(max, min));
break;
}
}
}
function genRan(max, min){
var genRan = Math.floor(Math.random() * (max - min) + min);
return genRan;
}
alert(pool.join('\n')); //to display the array of random numbers
}