Reputation: 167
I bought a JavaScript book and am working my way through. I've reached a part of the book that doesn't make sense. I'm hoping you guys and girls will be able to clarify as the book doesn't.
Please see the code below that generates 6 random numbers and renders them to a div with id=panel
.
function init(){
var panel = document.getElementById('panel');
var i, rand, temp, str, num = [];
for (i = 1; i < 50; i ++){
num[i] = i;
}
for (i = 1; i < 50; i ++){
rand = Math.ceil(Math.random()*49);
temp = num[i];
num[i] = num[rand];
num[rand] = temp;
}
str = 'Your six lucky numbers:<br>';
for (i = 1; i < 7; i ++){
str += num[i];
if (i !==6){str += ' - ';}
}
panel.innerHTML += str;
}
document.addEventListener('DOMContentLoaded', init, false);
The book says that the second loop (that initilizes the random variable) contains a sort algorithm that ensures no two elements contain the same number.
I'm not sure how this is possible, I don't see any code in there that stops rand
containing a duplicate number and consequently having that value stored in num
. The book doesn't really provide much of an explanation of what is going on.
Could someone please let me know how, if at all, loop two is preventing 'num` from containing the same number?
Thanks all
P.S. Sorry if this question doesn't adhere to Stack Overflow guidelines. I don't come on here often, only when I get really stuck and can't find an answer elsewhere.
Upvotes: 0
Views: 83
Reputation: 23850
You can think of the two loops as follows: the first one generates a deck of 49 "cards" (represented here by the numbers 1 through 49). The second loop then shuffles those "cards", by repeatedly swapping each card with a random one.
Note there are two issues with the code. First, it is unnecessary to shuffle the entire array when only 6 elements will be selected. So the second loop could end at 6 instead of 50.
But there is a more serious issue with the code, it uses the wrong algorithm to shuffle array elements. This algorithm does not produce all possible permutations of the elements with the same probability.
Here's the correct version:
for (i = 1; i < 50; i ++){
rand = i + Math.floor(Math.random()*(50 - i));
temp = num[i];
num[i] = num[rand];
num[rand] = temp;
}
The idea is to swap the current element in the loop, only with a subsequent element (including itself). Note that if you write the above loop to run backwards (i.e. from 49 to 1) it makes it slightly more simple and I prefer that approach.
Upvotes: 2
Reputation: 933
The first for loop is just creating an array of 49 elements, with each array element being equal to its index:
num[1] = 1
num[2] = 2
etc.
The second for loop, which is the focus of your question, randomly shuffles this ordered array.
As an Example:
1st iteration of the for loop, rand gets the value of say 23, the logic in the loop then swops the value in num[23] with the value in num[1] so that you end up with:
num[1] being equal to 23 (because num[23] was equal to 23 as per above)
num[23] being equal to 1
2nd iteration of the for loop, rand gets the value of say 18, the logic in the loop then swops the value in num[18] with the value in num[2] so that you end up with:
num[2] being equal to 18 (because num[18] was equal to 18 as per above)
num[18] being equal to 2
This will happen 49 times.
This is also the reason for Math.random() being multiplied with 49, there is only 49 array elements with values.
TL;DR; Ordered array gets shuffled.
Upvotes: 1
Reputation: 3692
This loops fills and array with 50 integers from 1 to 50.
Then it just mixes them. The rand variable is used to point a random index in the array.
Upvotes: 1
Reputation: 19475
This loop creates a sorted array from 1 to 49:
for (i = 1; i < 50; i ++){
num[i] = i;
}
This loop reorders each position (i
) of the array with another random position rand
by swapping the two. It’s not generating new random numbers, just randomly reordering existing numbers. rand
is an index, not a value in this case. No two numbers can be the same because the first loop only placed one instance of each number in the array.
for (i = 1; i < 50; i ++){
rand = Math.ceil(Math.random()*49);
temp = num[i];
num[i] = num[rand];
num[rand] = temp;
}
Upvotes: 1