Undefined Element Javascript Array - javascript

I have a problem. When I shuffle a array starting from position 1 and ending on position 49, one element seems to be undefined when outputted in the console.
for (var i = 49; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = genNr[i];
genNr[i] = genNr[j];
genNr[j] = temp;
}
Please help me.

I'm thinking that genNr contains 49 elements. The first time the loop runs, i will be 49 so you're trying to access genNr[49]. But, since array indexes start at zero, genNr[49] is undefined.
You need to start the loop with i equal to the length of the array minus 1, and stop when i is less than zero.
for (var i = genNr.length - 1; i >= 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = genNr[i];
genNr[i] = genNr[j];
genNr[j] = temp;
}

Related

Deleting value from array in Javascript using method (function)

Im just creating a simple game using javascript. im just stuck in deleting a value from array.
I have an array for player one ( for player one values are generated by random number). Value is called in a div when the current random number generated is displayed ....
Now i want to delete value from array if the current generated random number is similar to value in array of player one.
var playerone_arr = [];
for (var i = 0; i <= 3; i++) {
playerone_arr[i] = Math.floor(Math.random() * 10) + 1;
document.getElementById("playerone_no").innerHTML += playerone_arr[i];
}
function player_one_play() {
var random_no = Math.floor(Math.random() * 10) + 1;
document.getElementById("player_result").innerHTML = random_no;
for (var i = 0; i < playerone_arr.length; i++) {
if (playerone_arr[i] == random_no) {
playerone_arr.splice(playerone_arr[i], 1);
}
}
}
Splice expects an index, so provide the index of the element you want to remove.
var index = playerone_arr.indexOf(random_no);
if (index >= 0 ) {
playerone_arr.splice(index, 1);
}

Having Issue On Generating Random Numbers More Than Random Rage Number

I need to generate 30 Random Numbers between 1 to 20. I am using this code but this is making conflict since the loop number is bigger than the Random range (I guess!)
var arr1 = [];
for (var i = 0; i < 30;) {
var ran = Math.floor(Math.random() * 20) + 1;
if ( arr1.indexOf(ran) == -1)
arr1[i++] = ran;
}
can you please let me know why this is happening and how I can prevent this to create 30 random numbers?
Thanks
I created a fiddle here , have a look
https://jsbin.com/kagixi/edit?html,js,output
In first case, we are updating values by iterating over all the indices.
var list = new Array(30).fill(0);
list.forEach(function(d, index){
list[index] = Math.floor(Math.random() * 20) + 1;
});
console.log(list);
Another way of doing this is to initialize array just to loop and then simply create a new array with same length or replace the existing one as I did in this example.
var list2 = new Array(30).fill(0);
list2 = list2.map(function(){
return Math.floor(Math.random() * 20) + 1;
});
You miss the third argument on your for statement.
Try this:
var arr1 = [];
for (var i = 0; i < 30; i++) {
arr1[i] = Math.floor(Math.random() * 20) + 1;
}
Your code creates an infinite loop.
Your random numbers are between 1 and 20 but you want 30 of them in your array. The check for duplicates in the line if ( arr1.indexOf(ran) == -1) is guaranteed to return false after 20 iterations, creating an infinite loop.

JS probability of 10 people selecting the same number between 1 - 20

I'm pretty new to to javascript so please take it easy :)
I'm trying to figure out the probability of 10 people picking the same random number (1 - 20).
When I run the code it returns the same answer every time. I think something is wrong in the 3rd for loop when comparing numbers. Some help would be much appreciated, I've been stuck on this for 3 days now :(
var counter = 0;
//Determine probability (percentage)
for (var i = 1; i <=100; i++) {
//Create array with 10 elements and assign each element with random integer (1 - 20)
for (var j = 1; j <= 10; j++) {
var rndNum = [j];
rndNum = Math.random();
rndNum = Math.floor(rndNum * 20) + 1;
}
//Increment counter if match is found
for (var p1 = 1; p1 <= 9; p1++) {
for (var p2 = p1 + 1; p2 <= 10; p2++) {
if (rndNum[p1] == rndNum[p2]) {
counter++;
}
}
}
}
document.write("The probability of a match is: " + counter + "%");
Your code to make an "array" of random numbers is part of the problem. rndNum only has one value (it's an array with only one item in it, and you're overwriting it each time). You need array.push() to add values to an array.
You want something more like this:
var rndNum = [];
for (var j = 1; j <= 10; j++) {
rndNum.push(Math.floor(Math.random()* 20) + 1);
}
You want to know the probability that twenty people will pick the same random number?
alert("The probability of a match is: " + (Math.pow(.1, 20)*100)+ "%");
Or you want to know the probability that any two of twenty people will pick the same number?
alert("The probability of a match is: " + (Math.pow(.9, 20)*100)+ "%");
Your for loop should also start at 0, not one (the first element in an array is array[0]:
for (var p1 = 0; p1 <= 8; p1++) {
for (var p2 = p1 + 1; p2 <= 9; p2++) {
if (rndNum[p1] == rndNum[p2]) {
counter++;
}
}
}
You also need to divide your results by 10 because you have 1,000 tests (if you're checking to see if two match). If you want to see if they all match you would need something like:
var ordered = rndNum.sort();
if(ordered[0] == ordered[9])
counter2++;
Here's a fiddle of the combined array declaration and match checkers.

Javascript generate random unique number every time

Ok so i need to create four randomly generated numbers between 1-10 and they cannot be the same. so my thought is to add each number to an array but how can I check to see if the number is in the array, and if it is, re-generate the number and if it isnt add the new number to the array?
so basically it will go,
1.create new number and add to array
2.create second new number, check to see if it exist already, if it doesn't exist, add to array. If it does exist, re-create new number, check again etc...
3.same as above and so on.
You want what is called a 'random grab bag'. Consider you have a 'bag' of numbers, each number is only represented once in this bag. You take the numbers out, at random, for as many as you need.
The problem with some of the other solutions presented here is that they randomly generate the number, and check to see if it was already used. This will take longer and longer to complete (theoretically up to an infinite amount of time) because you are waiting for the random() function to return a value you don't already have (and it doesn't have to do that, it could give you 1-9 forever, but never return 10).
There are a lot of ways to implement a grab-bag type solution, each with varying degrees of cost (though, if done correctly, won't ever be infinite).
The most basic solution to your problem would be the following:
var grabBag = [1,2,3,4,5,6,7,8,9,10];
// randomize order of elements with a sort function that randomly returns -1/0/1
grabBag.sort(function(xx,yy){ return Math.floor(Math.random() * 3) - 1; })
function getNextRandom(){
return grabBag.shift();
};
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
This is of course destructive to the original grabBag array. And I'm not sure how 'truly random' that sort is, but for many applications it could be 'good enough'.
An slightly different approach would be to store all the unused elements in an array, randomly select an index, and then remove the element at that index. The cost here is how frequently you are creating/destroying arrays each time you remove an element.
Here are a couple versions using Matt's grabBag technique:
function getRandoms(numPicks) {
var nums = [1,2,3,4,5,6,7,8,9,10];
var selections = [];
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
You can see it work here: http://jsfiddle.net/jfriend00/b3MF3/.
And, here's a version that lets you pass in the range you want to cover:
function getRandoms(numPicks, low, high) {
var len = high - low + 1;
var nums = new Array(len);
var selections = [], i;
// initialize the array
for (i = 0; i < len; i++) {
nums[i] = i + low;
}
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
And a fiddle for that one: http://jsfiddle.net/jfriend00/UXnGB/
Use an array to see if the number has already been generated.
var randomArr = [], trackingArr = [],
targetCount = 4, currentCount = 0,
min = 1, max = 10,
rnd;
while (currentCount < targetCount) {
rnd = Math.floor(Math.random() * (max - min + 1)) + min;
if (!trackingArr[rnd]) {
trackingArr[rnd] = rnd;
randomArr[currentCount] = rnd;
currentCount += 1;
}
}
alert(randomArr); // Will contain four unique, random numbers between 1 and 10.
Working example: http://jsfiddle.net/FishBasketGordo/J4Ly7/
var a = [];
for (var i = 0; i < 5; i++) {
var r = Math.floor(Math.random()*10) + 1;
if(!(r in a))
a.push(r);
else
i--;
}
That'll do it for you. But be careful. If you make the number of random numbers generated greater than the may number (10) you'll hit an infinite loop.
I'm using a recursive function. The test function pick 6 unique value between 1 and 9.
//test(1, 9, 6);
function test(min, max, nbValue){
var result = recursValue(min, max, nbValue, []);
alert(result);
}
function recursValue(min, max, nbValue, result){
var randomNum = Math.random() * (max-min);
randomNum = Math.round(randomNum) + min;
if(!in_array(randomNum, result)){
result.push(randomNum);
nbValue--;
}
if(nbValue>0){
recursValue(min, max, nbValue, result);
}
return result;
}
function in_array(value, my_array){
for(var i=0;i< my_array.length; i++){
if(my_array[i] == value){
console.log(my_array+" val "+value);
return true;
}
}
return false;
}
Here is a recursive function what are you looking for.
"howMany" parameter is count of how many unique numbers you want to generate.
"randomize" parameter is biggest number that function can generate.
for example : rand(4,8) function returns an array that has 4 number in it, and the numbers are between 0 and 7 ( because as you know, Math.random() function generates numbers starting from zero to [given number - 1])
var array = [];
var isMatch= false;
function rand(howMany, randomize){
if( array.length < howMany){
var r = Math.floor( Math.random() * randomize );
for( var i = 0; i < howMany; i++ ){
if( array[i] !== r ){
isMatch= false;
continue;
} else {
isMatch= true;
break;
}
}
if( isMatch == false ){
array.push(r);
ran(howMany, randomize);
}
ran(howMany, randomize);
return array;
}
}
In your answer earlier, you do have a small bug. Instead of
var originalLength = grabBag.length;
for(var i = 0; i < originalLength .length; i++){
console.log(getNextRandom());
}
I believe you meant:
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
Thanks.

Javascript Random problem?

var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
alert(swf[i]); // swf[1] >> 2.swf
This case ,Random output One number.
How to Random output two different numbers ?
var swf = ['1.swf', '2.swf', '3.swf'],
// shuffle
swf = swf.sort(function () { return Math.floor(Math.random() * 3) - 1; });
// use swf[0]
// use swf[1]
Even though the above should work fine, for academical correctness and highest performance and compatibility, you may want to shuffle like this instead:
var n = swf.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = swf[i];
swf[i] = swf[j];
swf[j] = tmp;
}
Credits to tvanfosson and Fisher/Yates. :)
You can use splice to remove the chosen element, then simply select another randomly. The following leaves the original array intact, but if that's not necessary you can use the original and omit the copy. Shown using a loop to demonstrate how to select an arbitrary number of times upto the size of the original array.
var swf=["1.swf","2.swf","3.swf"];
var elementsToChoose = 2;
var copy = swf.slice(0);
var chosen = [];
for (var j = 0; j < elementsToChoose && copy.length; ++j) {
var i = Math.floor(Math.random()*copy.length);
chosen.push( copy.splice(i,1) );
}
for (var j = 0, len = chosen.length; j < len; ++j) {
alert(chosen[j]);
}
I would prefer this way as the bounds are known (you are not getting a random number and comparing it what you already have. It could loop 1 or 1000 times).
var swf = ['1.swf', '2.swf', '3.swf'],
length = swf.length,
i = Math.floor(Math.random() * length);
firstRandom = swf[i];
// I originally used `delete` operator here. It doesn't remove the member, just
// set its value to `undefined`. Using `splice` is the correct way to do it.
swf.splice(i, 1);
length--;
var j = Math.floor(Math.random() * length),
secondRandom = swf[j];
alert(firstRandom + ' - ' + secondRandom);
Patrick DW informed me of delete operator just leaving the value as undefined. I did some Googling and came up with this alternate solution.
Be sure to check Tvanfosson's answer or Deceze's answer for cleaner/alternate solutions.
This is what I would do to require two numbers to be different (could be better answer out there)
var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
var j;
do {
j = Math.floor(Math.random()*swf.length);
} while (j === i);
alert(swf[i]);
alert(swf[j]);
Edit: should be j===i

Categories

Resources