How to check if a generated number already exists - javascript

This code below creates a random costumer number and prints it out with a simple console log, but one feature is missing: It should check if the same costumer number/ID has already been generated before. If so, it should walk through the process again, so a new random number is generated which then is unique. How can I do that with this code? As a programming newbie I unfortunately have NO clue how I could do that. Maybe a while loop and storing the generated number in a variable? Would be totally awesome if you can provide the code, combined with mine or build in the duplicate-checking feature.
function generateCostumerNum() {
// generating a random 8-digit number with numbers from 1 to 9
var zeroToNine = "";
for (counter = 0; counter <= 7; counter++) {
var randomNumber = Math.floor(Math.random() * 9) + 1;
zeroToNine += randomNumber;
}
// calculating the cross-sum of the generated number above
var numberforCrossSum = zeroToNine,
crossSum = 0;
while (numberforCrossSum) {
crossSum += numberforCrossSum % 10;
numberforCrossSum = Math.floor(numberforCrossSum / 10);
}
// building together the final costumer ID string.
var finalCostumerNum = "ID" + zeroToNine + crossSum;
console.log(finalCostumerNum);
};
generateCostumerNum();

You can use a simple while loop that runs as long as the generated number has already been generated:
var already_generated_nums = []; // an array of the numbers already generated
//...
var new_num = generateCostumerNum();
while (already_generated_nums.includes(new_num)) {
new_num = generateCostumerNum();
}
already_generated_nums.push(new_num);

Related

Why isn't my for loop in Javascript changing the variable amount?

I made a Javascript code that should take two numbers in an array, arrange them from lowest to highest, and then return the sum of every number between and including them. So sumAll(1, 4) // returns the sum of 1 + 2 + 3 + 4 which is 10. However, when I do it, my variable total does not change from 0 with my for loop.
var sumAll = function(arr) {
var lower = Math.min(arr[0], arr[1]);
var upper = Math.max(arr[0], arr[1]);
var total = 0;
for (var i = lower; i <= upper; i++) {
total += i;
}
return total;
}
This code should return 10 when using 1 and 4, but it gives 0 because var total = 0. When I manually change var total to equal 10, then it turns to ten, which means my for loop is not working the way it should, and I have no idea why. Any help is greatly appreciated, I am super new to coding and have been working on this for a while.
Also, this is a TDD project so it is attached to a spec js file. So the only other part of this code is not actually me calling the array but
module.exports = sumAll
The spec file asks for this:
var sumAll = require('./sumAll')
describe('sumAll', function() {
it('sums numbers within the range', function() {
expect(sumAll(1, 4)).toEqual(10);
});
The code in your question works well, however, if you still have issues you could try this:
function sumAll(n1, n2) {
var numbers = [];
numbers.length = Math.abs(n2-n1)+1; numbers.fill(0);
numbers = numbers.map((i, j) => (Math.min(n1,n2)+j))
return numbers.reduce((acc, i) => (acc+=i))
}
sumAll(1,4); //10

Random lottery number generator

What I'm trying to do is generate 6 random numbers, five in a range of 1-45 and one in a range of 1-25 for a Greek lottery game (Tzoker). The first 5 numbers should be unique. By pressing a button, I want to add these numbers to a div using jQuery (I have some working code for this part).
I thought it would be pretty easy using a loop, but I've found myself unable to check if the number generated already exists. The loop would only contain the first 5 numbers, because the last number can be equal to one of the other 5.
Let me propose you some simpler solution.
Make a list of all numbers from 1 to 45.
Sort the list using Math.random (plus minus something, read the docs of Array.sort to find out) as the comparison function. You will get the list in random order.
Take 5 first items from the list.
Then, when you already have the numbers, put them all into your div.
This way you don't mix your logic (getting the numbers) with your presentation (putting stuff into the DOM).
I leave the implementation as an exercise for the reader. :)
Like this?
$(function() {
$('button').on('click', function(e) {
e.preventDefault();
var numArray = [];
while( numArray.length < 5 ) {
var number = Math.floor((Math.random() * 45 ) + 1);
if( $.inArray( number, numArray ) == -1 ) {
numArray.push( number );
}
}
numArray.push( Math.floor((Math.random() * 25 ) + 1) );
$('div').html( numArray.join("<br />") );
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Generate</button>
<div></div>
While this might be not exactly what you were asking for, if you would use lodash, this would be as simple as:
_.sample(_.range(1, 46), 5) // the 5 numbers from 1..45
_.random(1, 26) // one more from 1..25
This is why functional programming is so cool. You can read for example Javascript Allonge to find out more.
http://jsfiddle.net/015d05uu/
var tzoker = $("#tzoker");
var results = $("#results");
tzoker.click(function() {
results.empty();
var properResults = [];
var rand = 0;
var contains = false;
for (i = 1; i < 7; i++) {
do
{
(rand = Math.floor((Math.random() * (i != 6 ? 45 : 25)) + 1));
contains = properResults.indexOf(rand) > -1;
} while(contains)
results.append("<br />", rand, "<br />");
properResults.push(rand);
}
});
Here is the main idea of a solution. You can define the max value as a parameter for the random.
Then, check the existence of the item in a simple array with only the data you want.
You may use a general function which generates random numbers from 1 to maxValue, and adds them to an array only if they don't exist. Then, to display, cycle through the array items and append them to #randomNumbers.
HTML
<div id="randomNumbers"></div>
JS (with jQuery)
var randomNumbersArray = [];
$(function() {
generateRandomNumbers();
displayRandomNumbers();
});
function generateRandomNumbers() {
for (i = 0; i < 5; i++) {
generateRandomNumberFrom1To(45);
}
generateRandomNumberFrom1To(25);
}
function generateRandomNumberFrom1To(maxValue) {
var randomNumber;
do {
randomNumber = Math.ceil(Math.random() * maxValue);
} while ($.inArray(randomNumber, randomNumbersArray) > -1);
randomNumbersArray.push(randomNumber);
}
function displayRandomNumbers() {
for (i in randomNumbersArray) {
$("#randomNumbers").append(randomNumbersArray[i] + "<br>");
}
}

Code review --- Random link with memory -- Javascript

var links = ["http://www.google.com/", "http://www.cnn.com/", "http://www.bbc.com/", "http://www.nbc.com/"];
var random = Math.round(Math.random() * 4);
var previous = [];
previous.push(random);
return previous
for (var i = 0; i < previous.length; i++) {
while (previous[i] == random) {
random = Math.round(Math.random() * 4);
}
}
window.location = links[random];
I'm trying to make a code that will be used to lead users to a random site from a set of sites. This will be activated by a button in google sites, I just haven't gotten to the html part. Anyways, when I try to run this code in jsfiddle, the output is just a blank screen. Whats wrong? here's my logic
An array of the set sites.
'random' picks a number between 0 and 4, which corresponds to the sites in the array
an empty array
This pushes 'random's output to the empty array
This for loop checks to see if there is any data in the empty array
While loop says "ok, if random chooses a number already in the array 'previous', I will run random again.
Once an unchosen number is outputted, a new window opens to the chosen site.
Sadly, it's not performing this way. Any tips?
Edit: Jsfiddle
I think a slight reworking of the code might do the trick with particular emphasis on removing the loop:
var links = ["http://www.google.com/", "http://www.cnn.com/", "http://www.bbc.com/", "http://www.nbc.com/"];
var previous = [];
function showLink() {
if (previous.length !== links.length) {
var random = Math.round(Math.random() * ((links.length - 1) - 0) + 0 );
if (previous.indexOf(links[random]) > -1) {
showLink();
} else {
console.log(links[random], previous)
previous.push(links[random]);
}
} else {
console.log('No more links');
}
}
And at this point just keep calling showLink until you run out of links.
Demo
var links = ["http://www.google.com/", "http://www.cnn.com/", "http://www.bbc.com/", "http://www.nbc.com/"];
var random = Math.round(Math.random() * 4);
var previous = [];
previous.push(random);
for (var i = 0; i < previous.length; i++) {
while (previous[i] == random) {
random = Math.round(Math.random() * 4);
}
}
window.location = links[random];
You were missing a bracket, and you had a return statement before your for loop. So of course it wasn't working since the code under the return statement was unreachable the way you had it written.

Generate unique number within range (0 - X), keeping a history to prevent duplicates

I ran into the challenge where I need a function that returns a random number within a given range from 0 - X. Not only that, but I require the number returned to be unique; not duplicating numbers that have already been returned on previous calls to the function.
Optionally, when this is done (e.g. the range has been 'exhausted'), just return a random number within the range.
How would one go about doing this?
This should do it:
function makeRandomRange(x) {
var used = new Array(x),
exhausted = false;
return function getRandom() {
var random = Math.floor(Math.random() * x);
if (exhausted) {
return random;
} else {
for (var i=0; i<x; i++) {
random = (random + 1) % x;
if (random in used)
continue;
used[random] = true;
return random;
}
// no free place found
exhausted = true;
used = null; // free memory
return random;
}
};
}
Usage:
var generate = makeRandomRange(20);
var x1 = generate(),
x2 = generate(),
...
Although it works, it has no good performance when the x-th random is generated - it searches the whole list for a free place. This algorithm, a step-by-step Fisher–Yates shuffle, from the question Unique (non-repeating) random numbers in O(1)?, will perform better:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
pointer = (pointer-1+x) % x;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
return range[pointer] = num;
};
}
(Demo at jsfiddle.net)
Extended version which does only generate one "group" of unique numbers:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
if (range) {
pointer--;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
range[pointer] = num;
if (pointer <= 0) { // first x numbers had been unique
range = null; // free memory;
}
return num;
} else {
return Math.floor(Math.random() * x);
}
};
}
(Demo)
You got some great programming answer. Here's one with a more theoretical flavor to complete your panorama :-)
Your problem is called "sampling" or "subset sampling" and there are several ways you could do this. Let N be the range you are sampling frame (i.e., N=X+1) and M be the size of your sample (the number of elements you want to pick).
if N is much larger than M, you'll want to use an algorithm such as the one suggested by Bentley and Floyd in his column "Programming Pearls: a sample of brilliance" (temporarily available without ACM's lock screen here), I really recommend this as they explicitly give code and discuss in terms of hash tables, etc.; there a few neat tricks in there
if N is within the same range as M, then you might want to use the Fisher-Yates shuffle but stop after only M steps (instead of N)
if you don't really know then the algorithm on page 647 of Devroye's book on random generation is pretty fast.
I wrote this function. It keeps its own array with a history of generated numbers, preventing initial duplicates, continuing to output a random number if all numbers in the range have been outputted once:
// Generates a unique number from a range
// keeps track of generated numbers in a history array
// if all numbers in the range have been returned once, keep outputting random numbers within the range
var UniqueRandom = { NumHistory: new Array(), generate: function(maxNum) {
var current = Math.round(Math.random()*(maxNum-1));
if (maxNum > 1 && this.NumHistory.length > 0) {
if (this.NumHistory.length != maxNum) {
while($.inArray(current, this.NumHistory) != -1) { current = Math.round(Math.random()*(maxNum-1)); }
this.NumHistory.push(current);
return current;
} else {
//unique numbers done, continue outputting random numbers, or we could reset the history array (NumHistory = [];)
return current;
}
} else {
//first time only
this.NumHistory.push(current);
return current;
}
}
};
Here's a working Fiddle
I hope this is of use to someone!
Edit: as pointed out by Pointy below, it might get slow with a large range (here is a
fiddle, going over a range from 0-1000, which seems to run fine). However; I didn't require a very large range, so perhaps this function is indeed not suited if you look to generate and keep track of an enormous range.
You may try generating the number using the current date and time value which would make it unique. To make it within the range, you may have to use some mathematical function.

Random Number with javascript or jquery

I am trying to make a script to pick random number between two numbers . but it picks same number sometimes. i donot want to repeat same number until array is finished .
Here is my code
$(document).ready(function () {
abc();
test = array();
function abc() {
res = randomXToY(1, 10, 0);
$('#img' + res).fadeTo(1200, 1);
//$(this).addClass('activeImg');
//});
setTimeout(function () {
removeClassImg(res)
}, 3000);
}
function removeClassImg(res) {
$('#img' + res).fadeTo(1200, 0.1);
//$('#img' + res).removeClass('activeImg');
abc();
}
function randomXToY(minVal, maxVal, floatVal) {
var randVal = minVal + (Math.random() * (maxVal - minVal));
return typeof floatVal == 'undefined' ? Math.round(randVal) : randVal.toFixed(floatVal);
}
});
Does Anybody have idea about this ...
You'll have to maintain a list of numbers that have already been generated, and check against this list. Re-generate a new number if you find a dupe.
If you do not want the random numbers repeating themselves you have to keep track of the some way.
If you have the range you are dealing with is relatively small, you can create an array with all possible results and simply randomly pick out of it.
function Randomizer(minVal, maxVal, floatVal){
var possible_results = []; // for larger arrays you can build this using a loop of course
var randomization_array = [];
var count = minVal;
var incrementor = floatVal || 1; // set the distance between possible values (if floatVal equals 0 we round to 1)
while (count <= maxVal) {
possible_results.push(count);
count += incrementor;
}
this.run = function(){
// if randomization_array is empty set posssible results into it
randomization_array = randomization_array.length ? randomization_array : $.merge(randomization_array, possible_results);
// pick a random element within the array
var rand = Math.floor(Math.random()*randomization_array.length);
// return the relevant element
return randomization_array.splice(rand,1)[0];
}
}
and in order to use it (it creates a specialized object for each possible range):
rand = new Randomizer(1,10,0);
rand.run();
note that this approach does not work well for very large ranges

Categories

Resources