# The following algorithm is due to Bob Floyd and is
# described in Jon Bentley's, _More Programming Pearls_
# (1988), on p. 143.
#
# In this Perl implementation, I use a hash as an efficient,
# randomly-addressable series that supports insertion in
# O(1) time. This implementation selects subsets of size $m
# from the range [0,$n], without replacement. (The original
# from Bentley's book used the range [1,n]).
sub randomly_permuted_subset_of_range {
my ($m, $n) = @_;
my (@result, %series, $head);
for (my $j = $n-$m+1; $j <= $n; $j++) {
my $t = int rand($j+1);
if (exists $series{$t}) {
# insert $j into series after $t
@series{$t,$j} = ($j, $series{$t});
}
else {
# prefix $t to series
($head, $series{$t}) = ($t, $head);
}
}
for ($n = $head; defined $n; $n = $series{$n}) {
push @result, $n;
}
return \@result;
}
####
use Data::Dumper;
$Data::Dumper::Indent = 0;
print Dumper( randomly_permuted_subset_of_range(5, 10) );
print Dumper( randomly_permuted_subset_of_range(11, 10) );
print Dumper( randomly_permuted_subset_of_range(5, 2**48) );
####
$VAR1 = [2,1,7,0,5];
$VAR1 = [7,8,1,5,3,2,4,10,0,9,6];
$VAR1 = ['211572034652645','198222342410498',
'42862092043890','253205057797894',
'185109518737615'];