Make every item in a list point to another item
in a list, without pointing at itself. The
middle part is needed for the special case
where everyone has a "partner" except for the last
person. In other words, in the list 1-2-3,
if 1 points to 2 and 2 points to 1, then
nobody can point to 3 so some swapping must be
done. Inspired by the
Kris Kringle node.
use strict;
my @one = (1..10); ## Sample set
my %point;
my ($x,$y);
my $total=0;
for $x (@one) {
$total++;
{
## Pick any list element but $x:
redo while ($y = $one[rand @one]) eq $x;
## Special case: nobody left to point to
if ($total==@one && !$point{$x}) {
$total = $point{$y}; ## Recycling $total
$point{$y}=$x;
$point{$x}=$total;
last;
}
redo if $point{$y};
$point{$y}=$x;
}
}
print "$x => $point{$x}\n" while $x=$one[$x++];