Why not unique numbers are still coming? - javascript

I need to generate the unique numbers, join it with the letter and push to array.
arr = []
for (var i = 0; i < 5; i++) {
function generateRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
var randomNum = generateRandomNumber(1, 15);
if (!arr.includes(randomNum)) {
arr.push('B' + randomNum.toString())
} else {
if (arr.length < 5) {
return generateRandomNumber(min, max)
} else break
}
}
I have provisioned uniqueness check, however the same values are still coming.

Condition only checked once in the loop.
Also if the condition is in the else state, there is a chance that there will also be same number as previous.
You can use this approach
let arr = []
function generateRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function add(){
var randomNum = generateRandomNumber(1, 15);
if(arr.length < 5){
if (!arr.includes('B' + randomNum.toString())) {
arr.push('B' + randomNum.toString())
}
add()
}
}
add()
console.log(arr)

I have provisioned uniqueness check, however the same values are still coming.
The uniqueness check is incorrect.
The array contains only strings starting with letter 'B' (added by the line arr.push('B' + randomNum.toString())) while the uniqueness check searches for numbers.
The call arr.includes(randomNum) always returns false. Each and every generated value of randomNum is prefixed with 'B' and pushed into the array, no matter what the array contains.
Try a simpler approach: generate numbers, add them to the list if they are not already there, stop when the list is large enough (five items).
Then run through the list and add the 'B' prefix to each item.
Like this:
function generateRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
// Generate 5 unique random numbers between 1 and 15
let arr = []
while (arr.length < 5) {
let num = generateRandomNumber(1, 15);
// Ignore a value that has already been generated
if (!arr.includes(num)) {
arr.push(num);
}
}
// Add the 'B' prefix to the generated numbers
arr = arr.map((num) => `B${num}`);
console.log(arr);

Related

Generate a random number without repeating a previous number

I need to generate a random number without repeating a previous number. This is my code:
getRandomInt( max:number, min:number ) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
It gives me the generated random number but keeps repeating the same number.
Example:
1,2,3,4,4
and in the second call:
1,12,3,14,15
You could easely do this:
Object.defineProperty(Array.prototype, 'shuffle', {
value: function() {
for (let i = this.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
[this[i], this[j]] = [this[j], this[i]]
}
return this
}
})
var numArray = Array.from(Array(10).keys()) //generate an array with number from 0 to 10
numArray.shuffle()
the .shuffle() method will randomly take one at a time off the array and print it out.

Generating an array with 3 unique numbers

I'm trying to create an array with three unique random numbers between 1 and 14. I've found similar questions on Stackoverflow and used the code to help me create my existing code.
It works well most of the time, but occasionaly it will create an array with two of the same numbers. Here is the offending code:
function noDuplicates (sideRandom) {
sideArray.splice(sideRandom, 1);
let sideRandom2 = Math.floor(Math.random() * 14) + 1;
sideArray.push(sideRandom2);
console.log("I've had to add " + sideRandom2)
}
function sortNumbers(array) {
array.sort(function(a, b) {
return a - b;
});
}
document.getElementById("randomiser").addEventListener("click", function () {
for (let i = 0; sideArray.length <3; i++) {
let sideRandom = Math.floor(Math.random() * 14) + 1;
console.log(sideRandom);
if (sideArray.includes(sideRandom) === false) {
sideArray.push(sideRandom);
} else {
noDuplicates(sideRandom);
};
}
console.log(sideArray);
});
I suspect the issue is that sometimes the noDuplicates function generates the same random number as sideRandom, but I can't see a way around it. can you help?
Use set with while loop to make sure we got required number of unique random numbers
// Get unique random indexes
const random = (num, count) => {
const set = new Set();
while (set.size < count) {
set.add(Math.floor(Math.random() * num) + 1);
}
return [...set];
};
document.getElementById("randomiser").addEventListener("click", function () {
console.log(random(14, 3));
});
<button id="randomiser"> Get 3 random </button>
I take a look at your code: If there is a double you call noDuplicates and try to get a non double number but there you make some mistakes.
Why using Array#splice method? It will return the array without the first element (you don't user this result) and leave the original unchanged. So this line does anything. By the way why you want to delete the first element, youz didn't add the double random-number so there is anything do delete.
Afterwards you build another new randomnumber and push it to your array without checking. By this you get your dublettes.
Better way: If you finf a double set a flag on true and when you next add a number by this you can add your hint and reset the flag to false. So everything is one function.
document.getElementById("randomiser").addEventListener("click", function () {
let sideArray = [];
let double = false;
for (let i= 0; sideArray.length <3; i++) {
let sideRandom = Math.floor(Math.random() * 14) + 1;
console.log(sideRandom);
if (sideArray.includes(sideRandom) === false) {
if (double) {
double = false;
console.log("I've had to add " + sideRandom);
}
sideArray.push(sideRandom);
} else {
double = true;
}
}
console.log(sideArray.toString());
});
<button id='randomiser'>Click</button>
You can do this pretty easily with rando.js and slice. Plus, it's human-readable and cryptographically secure. randoSequence(1, 14) creates a shuffled array of all numbers from 1 through 14, and slice(0, 3) slices out the first three values from that shuffled array.
console.log(randoSequence(1, 14).slice(0, 3));
<script src="https://randojs.com/2.0.0.js"></script>

Javascript - function returning unexpected results

I am writing a couple of javascript functions to help randomly select articles from a JSON feed.
I have created a function called getRandomNumberFromRange which takes 2 parameters: the minimum and maximum numbers of a range of numbers to select from. The number of articles to be selected at random is provided via a data attribute on the DOM element which will eventually be populated with the articles.
The second function loadStories loops through the amount of articles which needs to be retrieved and calls the getRandomNumberFromRange function to get a number. This number will eventually be used as a key to select articles from the JSON feed array.
To ensure that a random number is not picked more than once, I have created an array to store previously picked numbers, which I will check against when the number is picked. If the number is in the array already, another number is picked, if it isn't it is added to the array.
This Codepen shows what I have so far. The code is also shown below:
var setupEmployeeStories = function () {
var
$element = $(".related-employee-stories"),
noOfStories = parseInt($element.attr("data-stories")),
arrSelectedNumbers = [],
getRandomNumberFromRange = function(min, max) {
var randomNumber = Math.floor(Math.random() * (max - min) + min);
if(arrSelectedNumbers.indexOf(randomNumber) === -1){
arrSelectedNumbers.push(randomNumber);
}else{
getRandomNumberFromRange(min, max);
}
return randomNumber;
},
loadStories = function(){
for(var i = 0; i < noOfStories; i++){
var rand = getRandomNumberFromRange(0, 4);
console.log(rand);
}
console.log(arrSelectedNumbers);
};
loadStories();
};
setupEmployeeStories();
Unfortunately I'm getting some odd results from the functions when the functions select the same random number multiple times. For some reason getRandomNumberFromRange tends to return a completely different number than what was actually picked by the function. This can be seen by the differences in the (console) logged results and the final array - arrSelectedNumbers
getRandomNumberFromRange = function(min, max) {
var randomNumber = Math.floor(Math.random() * (max - min) + min);
if(arrSelectedNumbers.indexOf(randomNumber) === -1){
arrSelectedNumbers.push(randomNumber);
}else{
randomNumber = getRandomNumberFromRange(min, max);
}
return randomNumber;
}
You need to set getRandomNumberFromRange to randomNumber to get the result of the recursive function.
var setupEmployeeStories = function () {
var
$element = $(".related-employee-stories"),
noOfStories = parseInt($element.attr("data-stories")),
arrSelectedNumbers = [],
getRandomNumberFromRange = function(min, max) {
var randomNumber = Math.floor(Math.random() * (max - min) + min);
if(arrSelectedNumbers.indexOf(randomNumber) === -1){
arrSelectedNumbers.push(randomNumber);
}else{
randomNumber = getRandomNumberFromRange(min, max);
}
return randomNumber;
},
loadStories = function(){
for(var i = 0; i < noOfStories; i++){
var rand = getRandomNumberFromRange(0, 4);
//console.log(rand);
}
console.log(arrSelectedNumbers);
};
loadStories();
};
setupEmployeeStories();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="related-employee-stories" data-stories="3"></div>

How to properly create JQuery inArray if statement?

I am generating a list of random numbers. Each random number is added to an array, but I want to check that the same number isnt entered twice. I am having a lot of trouble trying to get the if statement to work with this and am not sure what I have done wrong.
I have created:
//INITIALISE VARS, ARRAYS
var uniquearr = [];
i = 0;
while (i < 30){
var min = 0;
var max = 29;
var random = Math.floor(Math.random() * (max - min + 1)) + min;
//SEARCH UNIQUE ARRAY FOR EXISTING
if (jQuery.inArray(random, uniquearr) > -1){
//ADD NUMBER TO UNIQUE ARRAY
uniquearr.push(random);
//*DO SOMETHING*
} //END IF
i++;
} //END WHILE
But the if statement never triggers. Can anyone point me in the right direction?
You need to test whether the random number does not exist in the array; only then should it be added to the array.
Also another problem with the logic was, you were not adding the 30 unique numbers always as the i variable was incremented outside the if condition. Here you do not have to use a different loop variable since you can check whether the destination array is of desired size
//INITIALISE VARS, ARRAYS
var uniquearr = [], min = 0, max = 29;
//SEARCH UNIQUE ARRAY FOR EXISTING
while (uniquearr.length < 30){
var random = Math.floor(Math.random() * (max - min + 1)) + min;
if (jQuery.inArray(random, uniquearr) == -1){
uniquearr.push(random);
}//END IF
}//END WHILE
console.log('uniquearr', uniquearr)
That's because your if statement always is false, your array is empty and as result $.inArray always returns -1, you should check whether the returned value is -1 or not.
while (uniquearr.length < 30) { // uniquearr.length !== 30
var min = 0,
max = 29,
random = Math.floor(Math.random() * (max - min + 1)) + min;
//SEARCH UNIQUE ARRAY FOR EXISTENCE
if (jQuery.inArray(random, uniquearr) === -1) {
//ADD NUMBER TO UNIQUE ARRAY
uniquearr.push(random);
}
}
http://jsfiddle.net/zzL7v/

JavaScript for Random Numbers with Recursion

I'm trying to create a javascript function that accepts 2 parameters min and max and generates a random number between the two integers. That part is easy.
Where things get rough is that I need to create a conditional that says
function generateNum (min, max) {
var randNumber = Math.ceil(Math.random()*(max - min)+min);
if (randNumber === max) {
// store the result (probably in an array) and generate a new
// number with the same behavior as randNumber (e.g. it is also
// stores it's total in the array and recursively "re-generates
// a new number until max is not hit)
}
}
The idea is to recursive-ise this so that a running total of the number of max hits is stored, combined, and then returned.
For example: The script receives min / max parameters of 5/10 generateNum(5,10){}. If the value generated by randNumber were 5, 6, 7, 8, or 9 then there would be no recursion and the function would return that value. If the value generated by randNumber is 10, then the value 10 is stored in an array and the function now "re-tries" recursively (meaning that as many times as 10 is generated, then that value is stored as an additional object in the array and the function re-tries). When the process stops (which could be infinite but has a parabolically decreasing probability of repeating with each recursion). The final number (5, 6, 7, 8, 9) would be added to the total of generated max values and the result would be returned.
Quite an unusual mathematic scenario, let me know how I can clarify if that doesn't make sense.
That part is easy.
Not as easy as you think... The algorithm that you have is broken; it will almost never give you the minimum value. Use the Math.floor method instead, and add one to the range:
var randNumber = Math.floor(Math.random() * (max - min + 1)) + min;
To do this recursively is simple, just call the method from itself:
function generateNum (min, max) {
var randNumber = Math.floor(Math.random()*(max - min + 1)) + min;
if (randNumber == max) {
randNumber += generateNum(min, max);
}
return randNumber;
}
You can also solve this without recursion:
function generateNum (min, max) {
var randNumber = 0;
do {
var num = Math.floor(Math.random()*(max - min + 1)) + min;
randNumber += num;
} while (num == max);
return randNumber;
}
There is no need to use an array in either case, as you don't need the seprate values in the end, you only need the sum of the values.
I assume that you don't really need a recursive solution since you tagged this for-loop. This will return the number of times the max number was picked:
function generateNum (min, max) {
var diff = max - min;
if(diff <= 0)
return;
for(var i = 0; diff == Math.floor(Math.random()*(diff + 1)); i++);
return i;
}
Example outputs:
generateNum(1,2) // 3
generateNum(1,2) // 1
generateNum(1,2) // 0
generateNum(5,10) // 0
generateNum(5,10) // 1
Two things:
1) the probability to roll 10 stays (theoretically the same on each roll (re-try)), the low probability is of hitting n times 10 in a row
2) I don't see why recursion is needed, what about a while loop?
var randNumber;
var arr = [];
while ((randNumber = Math.ceil(Math.random()*(max - min)+min)) === max) {
arr.push(
}
I'd consider an idea that you don't need to use not only recursion and arrays but not even a for loop.
I think you need a simple expression like this one (separated into three for clarity):
function generateNum (min, max)
{
var randTail = Math.floor(Math.random()*(max - min)+min);
var randRepeatMax = Math.floor(Math.log(Math.random()) / Math.log(1/(max-min+1)));
return randRepeatMax*max + randTail;
}
Assuming one random number is as good as another, this should give you the same distribution of values as the straightforward loop.
Recursive method:
function generateNum (min, max) {
var res = Math.floor(Math.random() * (max - min + 1)) + min;
return (res === max) ? [res].concat(generateNum(min, max)) : res;
}

Categories

Resources