Lotto generator javascript - javascript

Hallo by lotto generator code I got some numbers double in one "generate" cycle. This is the code:
function lottery() {
for (var i=0; i<=7; i++) {
var lottery = Math.floor(Math.random() * 49);
document.getElementById ("lotto" + i).innerHTML = lottery;
}
}
Who knows where is the problem? Thank You!

Just for fun: O(N) solution (other posted are O(N^2))
It uses the Fisher-Yates shuffle algorithm and then after the first 7 elements have been shuffled it takes them as is.
So, no need to check if any of the numbers have already been drawn:
const arr = Array(50).fill(0).map((_, i) => i);
const DRAW = 7;
const rand = (from, to) => Math.floor(Math.random() * (to - from + 1)) + from;
for (let i = 0; i < DRAW; ++i) {
const r = rand(i, arr.length - 1);
[arr[r], arr[i]] = [arr[i], arr[r]];
}
const selected = arr.slice(0, DRAW);
References:
Online demo

Like #JNK commented, you need to store used values to avoid using them again.
The easiest way to do this would be to store them in an array, and check if they've been used.
function lottery() {
var used = [];
for (var i=0; i<=7; i++) {
var lottery;
while(true) { // this loop keeps going until a new number is found
lottery = Math.floor(Math.random() * 49);
var newNum = true;
for(var j=0; j<used.length; j++) {
if(used[j] == lottery) {
newNum = false; // if already used, set newNum to false
break;
}
}
if(newNum) { // if not already used, then add num to used array
used.push(lottery);
break;
}
}
document.getElementById ("lotto" + i).innerHTML = lottery;
}
}

All credits to JNK for this one from his link. This isn't very intuitive (it's minimized, like in code golf), but it's an interesting solution.
Optimized random number generator (86 bytes):
var getRandomLottoNumbers = function () {
var n=[],i=0;
for(;++i<50;)
n.push(i);
for(;--i>6;)
n.splice(i*Math.random()|0,1);
return n
};
Full explanation here.

Similar approach as the others, however just using one loop.
function lottery() {
var winners = [];
while (winners.length < 7) {
var lottery = Math.floor(Math.random() * 49);
if (winners.indexOf(lottery) === -1) {
winners.push(lottery);
document.getElementById ("lotto" + winners.length).innerHTML = lottery;
}
}
}

Related

generate 2 different random numbers from an Array?

my only issue so far is when the ships have the same value, I get an error message if I'm using VSC.
TypeError: Assignment to constant variable.
I was trying to get to different values by using the condition but I think it doesn't work.
let grid = [[]];
const letters = "abc".toUpperCase();
// create the Grid
const createGrid = (size) => {
let row;
let col = 0;
for (row = 0; row < size; row++) {
grid[row] = [];
for (col = 0; col < size; col++) {
grid[row][col] = `${letters[row]}${col + 1}`;
}
}
};
createGrid(letters.length);
console.table(grid);
// Start the game
//create ships
const flatArray = grid.reduce((acc, curr) => {
return [...acc, ...curr];
}, []);
function getRandomNumber(len) {
return Math.floor(Math.random() * len);
}
const randomNumber1 = getRandomNumber(flatArray.length);
const randomNumber2 = getRandomNumber(flatArray.length);
while(randomNumber1 == randomNumber2) {
getRandomNumber();
}
var shipOne = flatArray[randomNumber1];
var shipTwo = flatArray[randomNumber2];
console.log(shipOne);
console.log(shipTwo);
Fix an infinite loop
I created a snippet from your example code and it runs forever in the error case you are describing.
A problem is that you have a while loop that will run forever:
while(randomNumber1 == randomNumber2) {
getRandomNumber();
}
You run this code as long as randomNumber1 and randomNumber2 are the same but you update neither of them in the loop so it can never be false.
Try this:
while(randomNumber1 == randomNumber2) {
randomNumber2 = getRandomNumber(flatArray.length);
}
You might also make your code a little smarter and remove elements from the flatArray array you have already chosen.
One other approach you could try is to create a function pickRandomEntries() that will pick N random entries from an array, without ever picking the same ones.
To do this, we shuffle a copy of your flatArray(), then pick the first two items.
This way we never have to check for the ships having the same value:
let grid = [[]];
const letters = "abc".toUpperCase();
const createGrid = (size) => {
let row;
let col = 0;
for (row = 0; row < size; row++) {
grid[row] = [];
for (col = 0; col < size; col++) {
grid[row][col] = `${letters[row]}${col + 1}`;
}
}
};
createGrid(letters.length);
const flatArray = grid.reduce((acc, curr) => {
return [...acc, ...curr];
}, []);
// Shuffle an array into a random order (using Fisher-Yates)
function shuffle(arr) {
for(let i = arr.length - 1; i > 0; i--) {
let index = Math.floor(Math.random() * (i + 1));
[arr[index], arr[i]] = [arr[i], arr[index]];
}
return arr;
}
// Pick count random items from the array
function pickRandomEntries(arr, count) {
let shuffled = shuffle([...arr]);
return shuffled.slice(0, count);
}
let [shipOne, shipTwo] = pickRandomEntries(flatArray, 2);
console.log( { shipOne, shipTwo });
Inside of your while loop if the two random numbers were the same you would be stuck inside an infinite loop. Like Peter stated.
To fix this use the code Peter stated but don't forget you still need to pass in the array length into this function. Otherwise you will have an error:
while(randomNumber1 == randomNumber2) {
randomNumber2 = getRandomNumber(flatArray.length);
}
Thanks!!

How to stop random letter picking from doing duplicate letters [duplicate]

I need help with writing some code that will create a random number from an array of 12 numbers and print it 9 times without dupes. This has been tough for me to accomplish. Any ideas?
var nums = [1,2,3,4,5,6,7,8,9,10,11,12];
var gen_nums = [];
function in_array(array, el) {
for(var i = 0 ; i < array.length; i++)
if(array[i] == el) return true;
return false;
}
function get_rand(array) {
var rand = array[Math.floor(Math.random()*array.length)];
if(!in_array(gen_nums, rand)) {
gen_nums.push(rand);
return rand;
}
return get_rand(array);
}
for(var i = 0; i < 9; i++) {
console.log(get_rand(nums));
}
The most effective and efficient way to do this is to shuffle your numbers then print the first nine of them. Use a good shuffle algorithm.What Thilo suggested will give you poor results. See here.
Edit
Here's a brief Knuth Shuffle algorithm example:
void shuffle(vector<int> nums)
{
for (int i = nums.size()-1; i >= 0; i--)
{
// this line is really shorthand, but gets the point across, I hope.
swap(nums[i],nums[rand()%i]);
}
}
Try this once:
//Here o is the array;
var testArr = [6, 7, 12, 15, 17, 20, 21];
shuffle = function(o){ //v1.0
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
shuffle(testArr);
This is relatively simple to do, the theory behind it is creating another array which keeps track of which elements of the array you have used.
var tempArray = new Array(12),i,r;
for (i=0;i<9;i++)
{
r = Math.floor(Math.random()*12); // Get a random index
if (tempArray[r] === undefined) // If the index hasn't been used yet
{
document.write(numberArray[r]); // Display it
tempArray[r] = true; // Flag it as have been used
}
else // Otherwise
{
i--; // Try again
}
}
Other methods include shuffling the array, removing used elements from the array, or moving used elements to the end of the array.
If I understand you correctly, you want to shuffle your array.
Loop a couple of times (length of array should do), and in every iteration, get two random array indexes and swap the two elements there. (Update: if you are really serious about this, this may not be the best algorithm).
You can then print the first nine array elements, which will be in random order and not repeat.
Here is a generic way of getting random numbers between min and max without duplicates:
function inArray(arr, el) {
for(var i = 0 ; i < arr.length; i++)
if(arr[i] == el) return true;
return false;
}
function getRandomIntNoDuplicates(min, max, DuplicateArr) {
var RandomInt = Math.floor(Math.random() * (max - min + 1)) + min;
if (DuplicateArr.length > (max-min) ) return false; // break endless recursion
if(!inArray(DuplicateArr, RandomInt)) {
DuplicateArr.push(RandomInt);
return RandomInt;
}
return getRandomIntNoDuplicates(min, max, DuplicateArr); //recurse
}
call with:
var duplicates =[];
for (var i = 1; i <= 6 ; i++) {
console.log(getRandomIntNoDuplicates(1,10,duplicates));
}
const nums = [1,2,3,4,5,6,7,8,9,10,11,12];
for(var i = 1 ; i < 10; i++){
result = nums[Math.floor(Math.random()*nums.length)];
const index = nums.indexOf(result);
nums.splice(index, 1);
console.log(i+' - '+result);
}

Best approach to random 10 numbers between 1 and 100 no dupes in javascript? [duplicate]

This question already has answers here:
Generate unique random numbers between 1 and 100
(32 answers)
Closed 4 years ago.
This has been asked dozens of times, but somehow, after reading many answers, I'm not convinced. I'm not cleared about the best way to do it, performance and code simplicity.
Should I set the list [1.. 100] and keep picking random (it will run 10 times) from there to another array, avoiding searching for it every new random?
Should I develop and run 10 times (at least) a random function to return a 1.. 100, checking if it is not a dupe and put it into an array?
Some Javascript function that I'm missing?
Thanks
You can use a while loop to generate random numbers with Math.random() and add the numbers to a Set which contains only unique values.
var randoms = new Set();
while(randoms.size<10){
randoms.add(1 + Math.floor(Math.random() * 100));
}
console.log([...randoms.values()]);
You can also just use an Array and check if the generated random number already exists in it before pushing it to the Array.
var randoms = [];
while(randoms.length<10){
var random = Math.ceil(1 + Math.floor(Math.random() * 100));
if(randoms.indexOf(random)==-1){
randoms.push(random);
}
}
console.log(randoms);
For a more generic function, you can use this:
function generateRandoms(min, max, numOfRandoms, unique){
/*min is the smallest possible generated number*/
/*max is the largest possible generated number*/
/*numOfRandoms is the number of random numbers to generate*/
/*unique is a boolean specifying whether the generated random numbers need to be unique*/
var getRandom = function(x, y){
return Math.floor(Math.random() * (x - y + 1) + y);
}
var randoms = [];
while(randoms.length<numOfRandoms){
var random = getRandom(min, max);
if(randoms.indexOf(random)==-1||!unique){
randoms.push(random);
}
}
return randoms;
}
function generateRandoms(min, max, numOfRandoms, unique){
var getRandom = function(x, y){
return Math.floor(Math.random() * (x - y + 1) + y);
}
var randoms = [];
while(randoms.length<numOfRandoms){
var random = getRandom(min, max);
if(randoms.indexOf(random)==-1||!unique){
randoms.push(random);
}
}
return randoms;
}
console.log(generateRandoms(1, 100, 10, true));
This technique creates N1 numbers (the total range) and shuffles them, then picks the top N2 number (how many we actually want), we'll use Fisher-Yates shuffle.
const n1 = 100;
const n2 = 10;
let pool = [...Array(n1).keys()];
var result = [];
while (result.length < n2) {
let index = Math.floor(Math.random() * pool.length);
result = result.concat(pool.splice(index, 1));
}
console.log(result);
var randomArray = [];
while(randomArray.length < 10) {
var random = Math.round(Math.random() * 100);
if(randomArray.indexOf(random) === -1) {
randomArray.push(random);
}
}
console.log(randomArray);
#2 would be the most efficient.
var nums = []
while(nums.length < 10) {
var n = Math.round(Math.random()*100);
if (!nums.includes(n)) nums.push(n);
}
console.log(nums);
You could also use Set in a newer browser, which would be a little faster than manually checking for existence:
var nums = new Set();
while(nums.size < 10) {
var n = Math.round(Math.random()*100);
nums.add(n);
}
console.log([...nums.values()]);
This function adds all numbers from betweenStart to betweenEnd, randomizes them over randomRuns loops and returns a list with amount entries:
function randomNumbersBetweenXAndY(betweenStart, betweenEnd, amount, randomRuns) {
if (betweenStart === void 0) { betweenStart = 0; }
if (betweenEnd === void 0) { betweenEnd = 100; }
if (amount === void 0) { amount = 10; }
if (randomRuns === void 0) { randomRuns = 1; }
//Verify parameters
var maxPossibleCandidates = Math.abs(betweenStart - betweenEnd) + 1;
if (amount > maxPossibleCandidates) {
console.warn("You cannot get more unique numbers between " + betweenStart + " and " + betweenStart + " than " + maxPossibleCandidates + ". " + amount + " is too many!");
amount = maxPossibleCandidates;
}
//array to return
var list = [];
//fill array
for (var index = betweenStart; index <= betweenEnd; index++) {
list.push(index);
}
//Randomize
while (randomRuns--) {
for (var index = 0; index < list.length; index++) {
var randomIndex = Math.floor(Math.random() * list.length);
var tmp = list[index];
list[index] = list[randomIndex];
list[randomIndex] = tmp;
}
}
//Return data
return list.slice(0, amount);
}
//TEST
console.log(randomNumbersBetweenXAndY(1, 100, 10));

Counting duplicate random numbers from a for loop

I am trying to create a score predictor based on a teams goal difference (football). I am new to JavaScript, and I have managed to get this far.
I want it to be like spinning a ten-sided dice 20 times + the team's goal difference. I have got this bit sorted I think. With my code now I have a list of random numbers logged in the console which is what I wanted. Now I would like to choose a number (e.g., 2) and see how many times this occurs in the list. I'd like to save this in a new variable called homeFinalScore (So if '2' occurs three times in the list of random numbers, the homeFinalScore variable should be 3). I've tried several things but have been unable to sort it yet!
Any help would be extremely helpful. Thank you in advance!
var homeFinalScore = 0;
function calculateScore(){
var homeTeam = document.getElementById("HomeTeam").value;
var awayTeam = document.getElementById("AwayTeam").value;
var homeGd = parseInt(document.getElementById("HomeGD").value);
var awayGd = parseInt(document.getElementById("AwayGD").value);
var homeGd = 20 + homeGd;
var awayGd = 15 + awayGd;
for (i = 0; i < homeGd; i++) {
var randNum = Math.floor(Math.random() * 11);
console.log(randNum);
}
}
You can create an array, use Array.prototype.push() to push randNum to the array, then use Array.prototype.filter(), .length to determine how many occurrences of a value are present within array.
var homeGd = 20 + 2;
var awayGd = 15 + 2;
var arr = [];
function countOccurrences(n, arr) {
return arr.filter(function(value) {
return value === n
}).length;
}
for (i = 0; i < homeGd; i++) {
var randNum = Math.floor(Math.random() * 11);
arr.push(randNum);
}
console.log(arr);
console.log(countOccurrences(2, arr));
Alternatively, you can increment a variable when randNum is equal to a value.
var homeGd = 20 + 2;
var awayGd = 15 + 2;
var n = 0;
var num = 2;
for (i = 0; i < homeGd; i++) {
var randNum = Math.floor(Math.random() * 11);
console.log(randNum);
if (randNum === num) {
++n
}
}
console.log("occurrences of 2:", n);
const homeGd = 10;
const randomNumbers = []; // array of random numbers
for (i = 0; i < homeGd; i++) {
randomNumbers.push(Math.floor(Math.random() * 11));
}
const countBy = randomNumbers.reduce((acc, current) => {
acc[current] = (acc[current] || 0) + 1;
return acc;
}, {});
console.log(countBy);

What am I doing wrong with this array?

Okay, trying to put together a numeric array and arrange it in ascending order. The more I look, the more I confuse myself. The alerts come up as "undefined." What am I overlooking?
var random = new Array();
function main() {
generate();
original();
ascending(random);
}
function generate() {
document.write("Here are 25 Random Numbers:<br><br>");
for (var i = 0; i < 25; i++) {
random[i] = document.write(Math.floor(Math.random() * 100) + ", ");
}
}
function original() {
var storage = "";
for (var i = 0; i < 25; i++) {
storage += random[i] + ", ";
}
alert(storage);
}
function ascending(random) {
var tempArray = random;
var storage = "";
random.sort(function (a, b) {
return a - b
});
for (i = 0; i < 25; i++) {
storage += tempArray[i] + ", ";
}
alert("ASCENDING- " + storage);
}
No need for document.write (not sure what were you trying to achieve with it), this is enough:
random[i] = Math.floor(Math.random() * 100);
Afterwards, if you need to convert it to a string for output, just join it:
random.join(",");
Here is your generate function:
var random = [];
function generate() {
document.write("Here are 25 Random Numbers:<br><br>");
for (var i = 0; i < 25; i++) {
random[i] = Math.floor(Math.random() * 100);
}
}
generate();
var str = random.join(', ');
document.write(str);
Note: try to avoid using document.write whenever you can.
Take out your document.write() call in generate(), that prints a number out to your HTML document, just assign it directly to your array. You're assigning the result of that print out to your array, which is definitely not what you want.

Categories