blokhead's approach is certainly the most general, and I'm glad he posted it. My naive approach for this case, however, would have been to use a simple modification of the Fisher-Yates shuffling algorithm (untested and not optimized):
This samples randomly with replacement, but you can keep track of the picks (in a hash), and discard any repeats. As blokhead noted, for the numbers you're looking at this would happen very rarely, and probably never during your use of the algorithm.sub random_pick { my ( $n, $arr ) = @_; my @idx = 0..$#$arr; my $i = 0; while ( $i < $n ) { my $j = $i + rand( @idx - $i ); @idx[ $i, $j ] = @idx[ $j, $i ]; ++$i; } return @{ $arr }[ sort { $a <=> $b } @idx[ 0 .. $n-1 ] ]; }
Zaxo's approach also uses FY, but doing a full shuffle each time. On the one hand this is more work than is necessary, but on the other List::Util::shuffle is a compiled extension, so it may end up being faster than the solution above.
the lowliest monk
In reply to Re: Sampling from Combination Space
by tlm
in thread Sampling from Combination Space
by AdriftOnMemoryBliss
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |