how to randomize an integer variable, with odds on certain numbers appearing - javascript

To get a random whole number between 0 and 4 inclusive, I use the following code:
var random = Math.floor(Math.random() * 5);
However I want the number 4 to be chosen twice as often as the other numbers. How would I go about doing getting a random number between 0-4 inclusive, but with the number 4 appearing twice as many times as 0-3?

I think the easist way is to add the number twice to the array:
var nums = [0, 1, 2, 3, 4, 4];
var index = Math.floor(Math.random() * 6);
var random = nums[index];
But for something more generic, you may have a table:
var nums = [0, 1, 2, 3, 4];
var odds = [0.16667, 0.16667, 0.16667, 0.16667, 0.33333];
var r = Math.random();
var i = 0;
while(r > 0)
r -= odds[i++];
var random = nums[i];

Just do it like this:
var random = Math.floor(Math.random() * 6);
if (random == 5) random = 4;

Is this of any use:
http://www.javascriptkit.com/javatutors/weighrandom2.shtml

Math.floor(Math.random() * 2) == 0 ? Math.floor(Math.random() * 5) : 4
Here, 4 has 50% chance coz of first random selector, adding up 20% for second random selector.

I like sje397's initial answer with the correction that Paddy is suggesting:
var nums = [0, 1, 2, 3, 4, 4];
var random = nums[Math.floor(Math.random() * 6)];

The technique behind your requirement is to use a Shuffle Bag random generator. More details: http://web.archive.org/web/20111203113141/http://kaioa.com:80/node/53

Related

Calculate percentile from set of numbers

For example if I have array of numbers like 3,5,8,1,2,3 and my input 1 , I want to calculate percentage of times the number is above all other number.
Here is what I coded so far
var arr = [3, 5, 8, 1, 2, 3];
var input = 2;
var counter = 0;
for (var key in arr) {
if (input > arr[key]) counter++;
}
console.log(counter);
I just came across this logic , but this does not give percentile between 0 to 100 , and also don't know it will be faster if I run with length of 1000 arrays.
When I see some python codes , its complex and not simple like this.. Please some one guide me to calculate percentile in fastest way possible via javascript.
You pretty much have it, you just have to calculate it by dividing counter by arr.length and then to format it as a percentage multiply by 100 and then use toFixed to truncate it to whichever precision you want.
const a = [3, 5, 8, 1, 2, 3]
const i = 2
const c = 0
for (const v of a) {
if (i > v) c++
}
const p = ((c / a.length) * 100).toFixed(2)
console.log(`${p}%`) // 16.67%
<input type="text" id="pointspossible"/>
<input type="text" id="pointsgiven" />
<input type="text" id="pointsperc" />
$(function(){
$('#pointspossible').on('input', function() {
calculate();
});
$('#pointsgiven').on('input', function() {
calculate();
});
function calculate(){
var pPos = parseInt($('#pointspossible').val());
var pEarned = parseInt($('#pointsgiven').val());
var perc="";
if(isNaN(pPos) || isNaN(pEarned)){
perc=" ";
}else{
perc = ((pEarned/pPos) * 100).toFixed(3);
}
$('#pointsperc').val(perc);
}
});
You could use Array.filter for collecting the matching numbers and then compute the percentage using the length of the initial array and the length of the filtered array.
var arr = [3, 5, 8, 1, 2, 3];
var input = 2;
var percentage = 100 / arr.length * arr.filter(v => input > v).length;
console.log(Math.round(100 * percentage ) / 100);
The same result can be obtained with Array.reduce as follows:

Create a function that returns unique random numbers and assigns that number to an individual variable

I am just getting started in programming and ran into this issue. The answers posted on the forum don't really help me out so here goes my question.
I am trying to create a function that generates four random numbers between 1-12. Once the numbers are generated, they are assigned to a individual variable.
var gem1;
var gem2;
var gem3;
var gem4;
function updateGem() {
gem1 = Math.floor(Math.random() * 12 + 1);
gem2 = Math.floor(Math.random() * 12 + 1);
gem3 = Math.floor(Math.random() * 12 + 1);
gem4 = Math.floor(Math.random() * 12 + 1);
}
As you can see sometimes the numbers generated are matching, which is not what I need. I need every var to have it's own unique number.
The value of gem 1 is 8
The value of gem 2 is 9
The value of gem 3 is 9
The value of gem 4 is 8
You could do something like this:
function generateRandomUnique(size) {
const unique = new Set();
while (unique.size < size) {
unique.add(Math.floor(Math.random() * 12 + 1));
}
return [...unique];
}
const [gem1, gem2, gem3, gem4] = generateRandomUnique(4);
console.log(gem1, gem2, gem3, gem4);
Store the variables in an array and check for the number in the array
var gem1;
var gem2;
var gem3;
var gem4;
var arr=[];
function updateGem() {
arr=[];
gem1 = Math.floor(Math.random() * 12 + 1);
if(arr.includes(gem1))
updateGem();
else
arr.push(gem1);
gem2 = Math.floor(Math.random() * 12 + 1);
if(arr.includes(gem2))
updateGem();
else
arr.push(gem2);
gem3 = Math.floor(Math.random() * 12 + 1);
if(arr.includes(gem3))
updateGem();
else
arr.push(gem3);
gem4 = Math.floor(Math.random() * 12 + 1);
if(arr.includes(gem4))
updateGem();
else
arr.push(gem4);
}
updateGem()
console.log(gem1)
console.log(gem2)
console.log(gem3)
console.log(gem4)
This is what I did to solve the issue:
function updateGem() {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
numbers.sort(() => {
return 0.5 - Math.random();
});
gem1 = numbers[0];
gem2 = numbers[1];
gem3 = numbers[2];
gem4 = numbers[3];
}
Generate a random number based on an array length. Swap with the last index and now again generate a number based on array length reducing by 1.
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var count = numbers.length;
function updateGem() {
gem1 = getRandomNumber();
gem2 = getRandomNumber();
gem3 = getRandomNumber();
gem4 = getRandomNumber();
console.log(gem1, gem2, gem3, gem4);
}
function getRandomNumber() {
if (count <= 0) {
count = numbers.length;
}
var randomIndex = Math.round(count * Math.random());
console.log("Random Number="+randomIndex);
var temp = numbers[randomIndex];
numbers[randomIndex] = numbers[count-1];
numbers[count-1] = temp;
count--; // next time do not generate this random number
return temp;
}

Javascript Random Image

Im doing a random image display as part of a lab and I cant get the third image to appear (scissors.png). Thats my javascript below..Help would be much appreciated!
var total = 0;
function Images(){
var img1 = document.getElementById('img1');
var x = Math.floor(Math.random()*2)+1;
/* Player one */
if (x ==1)
img1.src = 'rock.png';
else if (x==2)
img1.src = 'paper.png';
else if (x==3)
img1.src = 'scissors.png';
}
I'm doing a random image display as part of a lab and I can't get the third image to appear (scissors.png).
That's because you're multiplying your random number by 2, and then flooring it, which gives you a range of 0-2 (inclusive); which isn't a problem (given zero-based arrays) but your ifis expecting one-based array indexes.
Incidentally, I'd suggest:
var images = ['rock', 'paper', 'scissors'],
rand = Math.floor(Math.random() * images.length);
return images[rand] + '.png';
Leading to an implementation like so:
function getImage() {
var images = ['rock', 'paper', 'scissors'],
rand = Math.floor(Math.random() * images.length);
return images[rand] + '.png';
}
document.querySelector('button').addEventListener('click', function() {
console.log(getImage());
});
<button>Get an image</button>
Try this:
var x = Math.floor(Math.random()*3)+1;
I'd also suggest you use: if (x === 1).
Javascript Math.random() returns a float value between the range [0, 1) - meaning including 0 but up to 1 excluding 1.
So, the max value is 0.99 * 2 = 1.98 and incremented by 1 is 2.98. Floor value of that is 2.
Easiest solution would be just to multiply it by 3.
Math.random() ∈ [0,1)
⇒ Math.random() * 2 ∈ [0,2)
⇒ Math.floor(Math.random()*2) ∈ [0,1] ∩ ℤ = {0,1}
⇒ Math.floor(Math.random()*2) + 1 ∈ {1,2}
If you want a number of the set {1,2,3}, you should multiply by 3:
Math.random() ∈ [0,1)
⇒ Math.random() * 3 ∈ [0,3)
⇒ Math.floor(Math.random()*3) ∈ [0,2] ∩ ℤ = {0,1,2}
⇒ Math.floor(Math.random()*3) + 1 ∈ {1,2,3}
function Images(){
var rand = Math.floor(Math.random()*3), // pick a random number: 0, 1 or 2
results = [rock, paper, scissors]; // Array of names, ordered.
// pick the right index from the array, so if the random number was '1',
// so the value at that index is used, which is "paper".
document.getElementById('img1').src = results[rand] + '.png';
}
Just change your multiplier to 3.
Or even to variable, that equals number of possibility results.
Math.random return us 0 <= r < 1.
Then multiplying, we can to get 0 <= r*n < n float numbers.
Math.floor get us integers 0 <= k < n or, that equals 0 <= k <= n-1
You should to add 1 to this sequence, if you want to get [1, n],
but [0, n-1] is the best for array index with length n.
Here example of implementation:
function action(images){
document.getElementById('img1').src =
images[Math.floor(Math.random()*images.length)];
}
action([
'rock.png',
'scissors.png',
'paper.png',
'lizard.gif',
'Spok.jpg'
]);

Selecting from an array based on size

I'm currently working on a small game and got stuck on something I can't figure out.
I have an array with 5 items in, these items represent different positions, like this:
[1, 2, 3, 4, 5]
These are basically different lines that are used to place objects as the players goes further into the game.
Every 5 second new objects should appear, these come from another array, that looks something like this:
[1, 2]
// 1 = single item
// 2 = double item
1 and 2 are different types of objects, both require a different amount of lines.
The problem is that these items sometimes overlap and I can't figure out how to stop this.
You can see the problem from the output:
Items: [1, 2]
[Item of type 1] line: 3
[available lines] [1, 2, 3, 4, 5]
[Item of type 2] line: 2
[available lines] [1, 2, 4, 5]
[1, 5]
So item 1 (1 line) is placed on line 3, but for item 2 (2 lines), line 2 is select, because it's 2 lines wide, this will overlap with my first item.
So basically for item 2 only line 1 and 4 could be selected, but I can't seem to find any logic that would only select these.
It's probably going to be expanded into something around 20 lines with more objects, so I would need to find a way to select a line where the next one is available too.
Any ideas on how I can get started on this?
What I currently use is this:
var random = Math.floor(Math.random() * (start_lines.length - 1));
var line = start_lines[random];
// If it's a barrier, delete 2 rows instead (35)
if(type == 2) {
if(line == 5) {
xPos = this._lines[random - 1] - 35;
start_lines.splice(random - 1, 2);
} else {
xPos = this._lines[random] - 35;
start_lines.splice(random, 2);
}
} else {
start_lines.splice(random, 1);
}
What I did for now was first loop trough the array with lines and check if the next line is available, I then push those 2 lines into another array which I can select from.
if(type == 2) {
var options = [];
for(var i = 0 ; i < start_lines.length; i++) {
var f = start_lines[i];
var n = start_lines[i + 1];
if((f + 1) == n) {
options.push([f, n]);
}
}
var random = Math.floor(Math.random() * (options.length - 1));
var option = options[random];
var f = option[0];
var n = option[1];
xPos = this._lines[f] - 30;
start_lines.splice(f - 1, 2);
start_lines.splice(n - 1, 2);
} else {
var random = Math.floor(Math.random() * (start_lines.length - 1));
var line = start_lines[random];
start_lines.splice(random, 1);
}
I don't know whether this approach fits for your requirement, but it would be better if you can set the lines initially and randomly pick one when needed. This avoids a lot of confusion.
function getLines(){
var start_lines = [1, 2, 3, 4, 5], lines = [];
while(start_lines.length){
var type = Math.ceil(Math.random() * 2);
lines.push(start_lines.splice(0, type));
}
return lines;
}
var lines = getLines();
var random = Math.floor(Math.random() * lines.length);
console.log(lines.splice(random, 1));
Here I am selecting type randomly - either 1 or 2. You will have to make some changes in this.
jsbin : http://jsbin.com/upabom/3/edit

Producing a random number that is different each time

I need to produce a random number ranging between 2 and 5 which is different each time. For example, I don't want two 3's in a row, or two 5's in a row. I then have to feed this into a for() loop, like this:
for(var i = 0; i < noBoxes.length; i+=randNumber) {
//....
}
How do I go about doing this?
Generate a random number up to n-1 and add it on, modulo the original range (shifting because the min is not 0):
i = some random int from 2 to 5
delta = randInt(3) // range of possible values from 2 to 5 is 4, minus 1 to
// prevent getting all the way round to i again
nextval = (i-2+delta)%4+2 // shift i down by the minimum, add the
// delta and modulo the range
This works because it adds up to 1 below the range, so it can never get back to the original number. For example, i=3, random int 0 to 2, so the max is (i-2+2)%3+2=3%3+2=0+2=2.
function differentRandInt(min,max,current) {
var shiftedcurrent = current-min;
var range = max-min+1;
var delta = Math.floor((Math.random()*(range-1))+1);
return (shiftedcurrent + delta)%range + min;
}
So if i=3, then i-min is 1, the range after adding the delta is 2,3,4, modulo 4 yielding 2,3,0, so adding the min gives us 4,5,2.
Edit: more complete solution, and fixed off-by-one error:
var prev, randNumber;
for(var i = 0; i < noBoxes.length; i+=randNumber) {
do {
randNumber = 2 + Math.floor(Math.random() * 4);
} while(randNumber === prev);
prev = randNumber;
}
Like so: http://jsbin.com/eyitav/
var loopingValues = [2, 3, 4, 5],
len,
value,
rand;
while ( (len=loopingValues.length) ) {
rand = ~~( ( Math.random() % 1 ) * len);
value = loopingValues.splice(rand, 1)[0];
//alert( value )
}
Now you have your loop with value as the value 2, 3, 4 and 5 in random order.
Or easier to read: http://jsbin.com/ejizuw/
var loopingValues = [2, 3, 4, 5],
value,
rand;
while ( loopingValues.length ) {
rand = Math.random();
if ( rand === 1 ) {
rand = 0;
}
rand = rand * loopingValues.length;
rand = Math.floor(rand);
value = loopingValues[rand];
loopingValues.splice(rand, 1);
alert(value);
}
You can get your series in an array before you start looping-
var noBoxes={length:100};
var R= [2], r= 2, n= 2;
while(R.length<noBoxes.length){
n= R[R.length-1];
while(r== n) r= 2+Math.floor(Math.random()*4)
R.push(r);
}
And then loop through the array-
for(var i = 0; i < noBoxes.length; i+=R[i]) {
....
}

Categories

Resources