Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does this simple shuffle algorithm produce biased results? what is a simple reason?

Tags:

it seems that this simple shuffle algorithm will produce biased results:

# suppose $arr is filled with 1 to 52  for ($i < 0; $i < 52; $i++) {    $j = rand(0, 51);    # swap the items    $tmp = $arr[j];   $arr[j] = $arr[i];   $arr[i] = $tmp; } 

you can try it... instead of using 52, use 3 (suppose only 3 cards are used), and run it 10,000 times and tally up the results, you will see that the results are skewed towards certain patterns...

the question is... what is a simple explanation that it will happen?

the correct solution is to use something like

for ($i < 0; $i < 51; $i++) {  # last card need not swap    $j = rand($i, 51);        # don't touch the cards that already "settled"    # swap the items    $tmp = $arr[j];   $arr[j] = $arr[i];   $arr[i] = $tmp; } 

but the question is... why the first method, seemingly also totally random, will make the results biased?

Update 1: thanks for folks here pointing out that it needs to be rand($i, 51) for it to shuffle correctly.

like image 654
nonopolarity Avatar asked May 13 '09 17:05

nonopolarity


People also ask

What is shuffle in computer science?

A term used to describe the play style used with computer audio and other media players. In shuffle mode, instead of playing the files or songs in order, it will randomly select the next file or song to play. By default, this mode is disabled and needs to be enabled through the program before playing in this style.

How do you randomize a list algorithm?

A simple way to randomise the order is to make a new list of the correct size (20 in your case), iterate over the first list, and add each element in a random position to the second list.

How do I shuffle an optimally array?

Shuffle Array using Random Class We can iterate through the array elements in a for loop. Then, we use the Random class to generate a random index number. Then swap the current index element with the randomly generated index element. At the end of the for loop, we will have a randomly shuffled array.


1 Answers

See this:
The Danger of Naïveté (Coding Horror)

Let's look at your three card deck as an example. Using a 3 card deck, there are only 6 possible orders for the deck after a shuffle: 123, 132, 213, 231, 312, 321.

With your 1st algorithm there are 27 possible paths (outcomes) for the code, depending on the results of the rand() function at different points. Each of these outcomes are equally likely (unbiased). Each of these outcomes will map to the same single result from the list of 6 possible "real" shuffle results above. We now have 27 items and 6 buckets to put them in. Since 27 is not evenly divisible by 6, some of those 6 combinations must be over-represented.

With the 2nd algorithm there are 6 possible outcomes that map exactly to the 6 possible "real" shuffle results, and they should all be represented equally over time.

This is important because the buckets that are over-represented in the first algorithm are not random. The buckets selected for the bias are repeatable and predictable. So if you're building an online poker game and use the 1st algorithm a hacker could figure out you used the naive sort and from that work out that certain deck arrangements are much more likely to occur than others. Then they can place bets accordingly. They'll lose some, but they'll win much more than they lose and quickly put you out of business.

like image 89
12 revs, 2 users 92% Avatar answered Oct 26 '22 23:10

12 revs, 2 users 92%