in reply to Re^2: Array Shuffle
in thread Array Shuffle
Update (again: previous code that appeared here was broken): If you modify the Fisher-Yates algorithm to force every element to swap with a higher element (instead of possibly "swapping" with itself), then almost all derangements are possible; all derangements become possible (thought not equally likely) if you use a random position in the list as the first location to swap from, and allow some swaps to be skipped if the candidates are already deranged.
use strict; use warnings; sub derange { my @list = @_; # Swap every element with something higher my $start = int rand @list; for (0..($#list-1)) { my $this = ($start + $_) % @_; next if $list[$this] ne $_[$this] and $_ < $#list-1 and rand > .52 +; my $other = $_ + 1 + int rand($#list - $_); $other = ($start + $other) % @_; @list[$this,$other] = @list[$other,$this]; } "@list"; } my @ar = ('a'..'d'); print "@ar\n"; my %countem; $countem{derange @ar}++ for 1..5000; print "$_: $countem{$_}\n" for (sort keys %countem);
|
|---|