Randomizing an Array
Problem
You want to shuffle the elements of an array randomly. The obvious application is writing a card game, where you must shuffle a deck of cards, but it is equally applicable to any situation where you want to deal with elements of an array in a random order.
Solution
Swap each element in the array with another randomly selected, element:
# fisher_yates_shuffle( \@array ) : generate a random permutation
# of @array in place
sub fisher_yates_shuffle {
my $array = shift;
my $i;
for ($i = @$array; --$i; ) {
my $j = int rand ($i+1);
next if $i == $j;
@$array[$i,$j] = @$array[$j,$i];
}
}
fisher_yates_shuffle( \@array ); # permutes @array in placeOr, pick a random permutation using the code in Example 4.4:
$permutations = factorial( scalar @array ); @shuffle = @array [ n2perm( 1+int(rand $permutations), $#array ) ];
Discussion
Shuffling is a surprisingly tricky process. It’s easy to write a bad shuffle:
sub naive_shuffle { # don't do this
for (my $i = 0; $i < @_; $i++) {
my $j = int rand @_; # pick random element
($_[$i], $_[$j]) = ($_[$j], $_[$i]); # swap 'em
}
}This algorithm is biased; the list’s possible permutations don’t all have the same probability of being generated. The proof of this is simple: take the case where we’re passed a 3-element list. We generate three random numbers, each of which can have three possible values, yielding 27 possible outcomes here. There are only 6 permutations of the 3-element list, though. Because 27 isn’t evenly divisible by ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access