adding random value to array and comparing first two value js - javascript

I am trying to learn some simple things in js, so what i am trying to achieve is every time I get a random number I want to add it inside an array at he front, then compare the first two values make sure they are not [6,6]
function randomNumber() {
number = Math.floor((Math.random() * 6) + 1);
return number;
}
function addValue() {
var score = [];
score.unshift(randomNumber());
console.log(score);
return score;
}
At the moment what is happening, every time i call the randomNumber the array only stores one value, it does not append it to the list and overweights the previous.
What am I doing wrong and why is it working? thx

the variable you use to store the array needs to be created and passed through the argument list, or stored globally.
when you do var x = [] you are create a NEW empty array.
var score = [];
addValue(score);
addValue(score);
addValue(score);
function randomNumber() {
number = Math.floor((Math.random() * 6) + 1);
return number;
}
function addValue(score) {
score.unshift(randomNumber());
}
console.log(score)

Related

How to approach creating array of random numbers with no repeats

I’ve created a lotto number generator and am having trouble making sure no two sets of numbers come out the same. I want to first check that the next generated number doesn’t match a previous one in the array, if it does then generate a new number.
The code:
https://codesandbox.io/s/billowing-leaf-oqdt3?file=/index.html
You can do it step by step by replacing what you have line 46 by:
// Get a random number
var rnd = rand(high);
// If it is already in the array, get another
while (numList.includes(rnd)) {
rnd = rand(high);
}
// Now you know the value is unique, so you can add it to the list.
numList.unshift(rnd);
use a hash:
var numberHash = {}
var num1=generateNum(numberHash);
var num2=generateNum(numberHash);
function generateNum(numberHash) {
var num = rand();
while(numberHash[num]) {
num = rand();
}
numberHash[num]=true;
return num;
}

Randomize number on click but never the same number

I want to random a number on clicking button but I don't want same numbers to be randomized any solutions?
$('button').click(function(){
var nomeri = Math.floor(Math.random() * 100);
}
<button>დამაკლიკე</button>
You could use a recursive function to generate a unique number.
I am implementing the function with an array which will hold the value of the previously used numbers and the Math.random() to generate the random number.
steps:
Step 1. Create a function.
Step 2: Generate a random number
step 3: check if it exists in the array
step 4: if already exists then call the function again otherwise we have the unique random number.
if the function exceeds the max random numbers then it will return a negative number. You could handle this according to your need, you could reset the array or something like that.
Try this.
$('button').click(function(){
var nomeri = genRandomNum();
console.log(nomeri);
});
let random = [];
function genRandomNum() {
let randNum = Math.floor(Math.random() * 100);
if (random.length >= 100) {
return -1;
} else if (random.includes(randNum)) {
return genRandomNum();
} else {
random.push(randNum);
return randNum;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Random Number</button>
Here is a more efficient way to do this. Doing it the way Sohail proposed could result in many many function calls, especially once there have been a large share of the available numbers added to the array. Each time it finds a number that has been used before it calls the function again in search of a random number that has not been used yet. It could take a long time to find an unused number.
This way you are guaranteed to get an unused number the first time you call the function.
1) All possible answers are added to an array.
2) Then a random value from that array is returned.
3) The array is then modified to exclude the values already returned.
See: array.splice()
const allPossibleValues = [];
for(let i = 0; i < 100; i++){
allPossibleValues.push(i);
}
$('button').click(function(){
if(allPossibleValues.length){
let nomeri = returnRandomValueFromArray();
console.log(nomeri);
}
else {
console.log("No more values left");
}
});
function returnRandomValueFromArray() {
const randomIndex = Math.floor(Math.random() * allPossibleValues.length);
const randomValue = allPossibleValues[randomIndex];
allPossibleValues.splice(randomIndex, 1);
return randomValue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>დამაკლიკე</button>

Generate a non-repeating random number in JavaScript

How do I ensure that I don't get a repeat of a random number? Right now, this isn't working. I'm using a local array to store previous results.
getUniqueRandomNumber(x){
var index;
var viewedIndices = [];
index = Math.floor(Math.random() * (x));
if(viewedIndices.includes(index))
{
viewedIndices.push(index);
this.getUniqueRandomNumber(x);
}
else {
console.log(index);
return index;
}
}
You need to make viewedIndicies persistent, so that further calls of getUniqueRandomNumber can see elements previously added. Rather than keeping track of the indicies, it would probably be easier to keep track of just the plain numbers chosen. You can use a Set instead of an array for less computational complexity (.has is O(1), .includes is O(N)).
const makeGetUniqueRandomNumber = (x) => {
const chosenNumbers = new Set();
return () => {
if (chosenNumbers.size === x) {
throw new Error('No more uniques!');
}
let num;
do {
num = Math.floor(Math.random() * x);
} while (chosenNumbers.has(num));
chosenNumbers.add(num);
return num;
};
};
const getRand5 = makeGetUniqueRandomNumber(5);
console.log(
getRand5(),
getRand5(),
getRand5(),
getRand5(),
getRand5()
);
try {
getRand5();
} catch(e) {
console.log(e.message);
}
const anotherGetRand5 = makeGetUniqueRandomNumber(5);
console.log(
anotherGetRand5(),
anotherGetRand5(),
anotherGetRand5(),
anotherGetRand5(),
anotherGetRand5()
);
You may also generate the whole array of random numbers ahead of time, and then splice each time another is chosen, but that'll be inefficient when the number of possibilities is large but you only need a few random numbers. The right choice depends on the proportion of unique numbers needed in one session to the size of the random range.
If developing in an ancient environment which doesn't understand ES6 (ES2015) syntax, then you can use an array instead of a Set, and pass the code through Babel:
"use strict";
var makeGetUniqueRandomNumber = function makeGetUniqueRandomNumber(x) {
var chosenNumbers = [];
return function () {
if (chosenNumbers.length === x) {
throw new Error('No more uniques!');
}
var num;
do {
num = Math.floor(Math.random() * x);
} while (chosenNumbers.includes(num));
chosenNumbers.push(num);
return num;
};
};
var getRand5 = makeGetUniqueRandomNumber(5);
console.log(getRand5(), getRand5(), getRand5(), getRand5(), getRand5());
try {
getRand5();
} catch (e) {
console.log(e.message);
}
var anotherGetRand5 = makeGetUniqueRandomNumber(5);
console.log(anotherGetRand5(), anotherGetRand5(), anotherGetRand5(), anotherGetRand5(), anotherGetRand5());
You have 2 mistakes, oné is the array inside the function this cleared for each try, and then there is wrong logic ending up in an infinite loop.
const usedIndexes = [];
function getUniqueRandomNumber(x) {
const index = Math.floor(Math.random() * (x));
if (usedIndexes.includes(index)) {
return this.getUniqueRandomNumber(x);
} else {
console.log(index);
usedIndexes.push(index);
return index;
}
}
Also, I would think about using Set, in this situation instead of the array.
const usedIndexes = new Set();
function getUniqueRandomNumber(max, min = 0) {
const newNumber = Math.floor(Math.random() * (max - min) + min);
if (usedIndexes.has(newNumber)) {
return this.getUniqueRandomNumber(max, min);
} else {
usedIndexes.add(newNumber);
return newNumber;
}
}
I have also edited variables names to better reflect their actual use and added a minimum for a random number.
This is not working because every time you call getUniqueRandomNumber it re-initializes your viewedIndices array to empty array. So to make your code work declare this array above the function call.
Do you just want the code you wrote to work or do you want a better solution? Picking random numbers until you don't get a repeat is a recipe for disaster down the line as your program stalls for several seconds trying to find a number that hasn't been used. Sure if you're only asking for a few numbers maybe it won't take forever but then the code sits in your code base and 5 years from now someone else is using it not knowing there is a time bomb in the code. Imagine there are 10000 elements in the array and 9999 have been picked. It could easily take 1 million re-tries before it ends up picking the one unused index.
The code appears to be choosing indices with variable names like index and viewedIndices
One way to pick random elements is just just remove then from the array at random. If you need to make copy of the array
const array = ["a", "b", "c", "d", "e", "f", "g"];
while (array.length) {
const ndx = Math.random() * array.length | 0;
const elem = array.splice(ndx, 1)[0];
console.log(elem);
}
Note: using Math.random() * value | 0 to get a random 0 -> positive integer is faster than Math.floor(Math.random() * value) as | is an operator, not a function attached to the Math object that has to be checked on every call to see if it has been replaced.

How to generate a new random number (that's different from the previous random number)

I'm trying to change the following (that currently returns a random number from an array), so that each random number is different from the last one chosen.
function randomize(arr) {
return arr[Math.floor(Math.random()*arr.length)];
}
oracleImg = [];
for (var i=1;i<=6;i++) {
oracleImg.push(i);
}
randOracleImg = randomize(oracleImg);
I tried the following, but it's not always giving me a number different from the last number.
function randomize(arr) {
var arr = Math.floor(Math.random()*arr.length);
if(arr == this.lastSelected) {
randomize();
}
else {
this.lastSelected = arr;
return arr;
}
}
How can I fix this?
Your existing function's recursive randomize() call doesn't make sense because you don't pass it the arr argument and you don't do anything with its return value. That line should be:
return randomize(arr);
...except that by the time it gets to that line you have reassigned arr so that it no longer refers to the original array. Using an additional variable as in the following version should work.
Note that I've also added a test to make sure that if the array has only one element we return that item immediately because in that case it's not possible to select a different item each time. (The function returns undefined if the array is empty.)
function randomize(arr) {
if (arr.length < 2) return arr[0];
var num = Math.floor(Math.random()*arr.length);
if(num == this.lastSelected) {
return randomize(arr);
} else {
this.lastSelected = num;
return arr[num];
}
}
document.querySelector("button").addEventListener("click", function() {
console.log(randomize(["a","b","c","d"]));
});
<button>Test</button>
Note that your original function seemed to be returning a random array index, but the code shown in my answer returns a random array element.
Note also that the way you are calling your function means that within the function this is window - not sure if that's what you intended; it works, but basically lastSelected is a global variable.
Given that I'm not keen on creating global variables needlessly, here's an alternative implementation with no global variables, and without recursion because in my opinion a simple while loop is a more semantic way to implement the concept of "keep trying until x happens":
var randomize = function () {
var lastSelected, num;
return function randomize(arr) {
if (arr.length < 2) return arr[0];
while (lastSelected === (num = Math.floor(Math.random()*arr.length)));
lastSelected = num;
return arr[num];
};
}();
document.querySelector("button").addEventListener("click", function() {
console.log(randomize(["a","b","c","d"]));
});
<button>Test</button>
Below code is just an example, it will generate 99 numbers and all will be unique and random (Range is 0-1000), logic is simple just add random number in a temporary array and compare new random if it is already generated or not.
var tempArray = [];
var i=0;
while (i != 99) {
var random = Math.floor((Math.random() * 999) + 0);
if (tempArray.indexOf(random)==-1) {
tempArray.push(random);
i++;
} else {
continue;
}
}
console.log(tempArray);
here is a version which will ensure a random number that is always different from the last one. additionally you can control the max and min value of the generated random value. defaults are max: 100 and min: 1
var randomize = (function () {
var last;
return function randomize(min, max) {
max = typeof max != 'number' ? 100 : max;
min = typeof min != 'number' ? 1 : min;
var random = Math.floor(Math.random() * (max - min)) + min;
if (random == last) {
return randomize(min, max);
}
last = random;
return random;
};
})();
If you want to ALWAYS return a different number from an array then don't randomize, shuffle instead!*
The simplest fair (truly random) shuffling algorithm is the Fisher-Yates algorithm. Don't make the same mistake Microsoft did and try to abuse .sort() to implement a shuffle. Just implement Fisher-Yates (otherwise known as the Knuth shuffle):
// Fisher-Yates shuffle:
// Note: This function shuffles in-place, if you don't
// want the original array to change then pass a copy
// using [].slice()
function shuffle (theArray) {
var tmp;
for (var i=0; i<theArray.length;i++) {
// Generate random index into the array:
var j = Math.floor(Math.random()*theArray.length);
// Swap current item with random item:
tmp = theArray[i];
theArray[j] = theArray[i];
theArray[i] = tmp;
}
return theArray;
}
So just do:
shuffledOracleImg = shuffle(oracleImg.slice());
var i=0;
randOracleImg = shuffledOracleImg[i++]; // just get the next image
// to get a random image
How you want to handle running out of images is up to you. Media players like iTunes or the music player on iPhones, iPads and iPods give users the option of stop playing or repeat from beginning. Some card game software will reshuffle and start again.
*note: One of my pet-peeves is music player software that randomize instead of shuffle. Randomize is exactly the wrong thing to do because 1. some implementations don't check if the next song is the same as the current song so you get a song played twice (what you seem to want to avoid) and 2. some songs end up NEVER getting played. Shuffling and playing the shuffled playlist from beginning to end avoids both problems. CD player manufacturers got it right. MP3 player developers tend to get it wrong.

Use closure to sum numbers

Currently I have a closure in JS that looks like the following:
var addTo = function(num){
var add = function(inner){
return inner + num;
};
return add;
};
var sum = new addTo(1);
My goal is to use the above closure to compute the sum from 1 all the way to 100 (i.e. sum = 1+2+3+...+99+100). Any help? I know a loop is needed, but am unsure of what should go inside the loop and how to use closure to achieve the goal. Thanks guys.
Currently I have a closure in JS that looks like the following:
All functions create closures, they're only remarkable when advantage is taken of them. ;-)
var addTo = function(num){
I don't know why function expressions are used when declarations are clearer (to me):
function addTo(num) {
then there's:
var add = function(inner){
return inner + num;
}
return add;
}
Which (sticking with an expression) can be:
return function (inner) {return inner + num};
}
Then you call it with new:
var sum = new addTo(1);
which causes addTo to create a new object that is not used, so you might as well do:
var sum = addTo(1);
which produces exactly the same result. So:
function addTo(num) {
return function (inner) {return inner + num};
}
var sum = addTo(1);
document.write(sum(3));
However, this is really just a version of Currying, so that sum will just add the supplied value to whatever was initially supplied to addTo.
If you want to add all the numbers from 0 to some limit, you just need a loop, no closure required:
function sumTo(num) {
var total = 0;
for (var i = 0; i <= num; i++) {
total += i;
}
return total;
}
document.write(sumTo(5)); // 15
Note that supplying a negative number will result in an endless loop, you should protect against that (I'll leave it up to you to work out how).
Try
function sum(x) {
var input = x;
function add(y) {
return input + y;
}
return add;
}
//var sum1 = sum(2);
//console.log(sum1(3)); // 5
console.log(sum(2)(3)); //5
Maybe you want to use recursive instead of loops?
function addTo(initial) {
function add(adder) {
if (initial < 100) {
initial+=1
return add(adder+initial)
}
else {
return adder
}
}
return add(initial)
}
document.write(addTo(1))
As long as the initial values don't go over 100, it would just add with sum of all calculation before + itself + 1.
It looks like the addTo() function returns another function into sum that will add whatever you pass it to the original number (or I assume that's what you meant to write; the first thing to do is change the statement inside of add() to use a += instead of just + to make sure you save the result).
Since you want to add each number from 2 to 100 (since you already passed 1 into addTo()), try writing a for loop that runs from 2 to 100 passing each one into the sum() function to add them all together. Here's an example:
var sum = addTo(1);
for (var i=2; i<100; i++) sum(i);
var result = sum(100);
Here I added 100 after the loop since I wanted to grab the final result. You could also add 100 in the loop and use sum(0) to get the result without changing it after the loop.

Categories