Then something like this should do the trick:
#! perl -slw use strict; use Data::Dump qw[ pp ]; sub genPicker { my $fh = shift; my( @vals, @odds ); ( $vals[ @vals ], $odds[ @odds ] ) = split( ' +' ) for <$fh>; ## Sort if not sorted my @order = sort{ $odds[ $a ] <=> $odds[ $b ] } 0 .. $#odds; @odds = @odds[ @order ]; @vals = @vals[ @order ]; ## Calculate and accumulate break points my $t = 0; $t += $_ for @odds; $_ /= $t for @odds; $odds[ $_ + 1 ] += $odds[ $_ ] for 0 .. $#odds - 1; ## Generate a subroutine to do the picking return sub { my $r = rand(); $r < $odds[ $_ ] and return $vals[ $_ ] for 0 .. $#odds; }; } my $pick = genPicker( *DATA ); ## run a quick test my %tally; ++$tally{ $pick->() } for 1 .. 10e6; pp \%tally; __DATA__ A 1e-7 B 20e-7 C 10e-5
Produces:
C:\test>1127420 { A => 9949, B => 195307, C => 9794744 } C:\test>1127420 { A => 10077, B => 196613, C => 9793310 }
In reply to Re^3: an algorithm to randomly pick items that are present at different frequencies
by BrowserUk
in thread an algorithm to randomly pick items that are present at different frequencies
by efoss
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |