[
0 0 0 0 0 5.88235294117647
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 23.5294117647059
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 47.0588235294118
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 100
]
####
foo: 5.88235294117647%
bar: 17.6470588235294%
baz: 23.5294117647059%
quux: 52.9411764705882%
####
c:\test>junk -N=1e2
foo frequency 4.000%
bar frequency 18.000%
baz frequency 23.000%
quux frequency 55.000%
c:\test>junk -N=1e3
foo frequency 5.300%
bar frequency 15.400%
baz frequency 25.600%
quux frequency 53.700%
c:\test>junk -N=1e4
foo frequency 5.640%
bar frequency 17.690%
baz frequency 23.370%
quux frequency 53.300%
c:\test>junk -N=1e5
foo frequency 5.961%
bar frequency 17.379%
baz frequency 23.683%
quux frequency 52.977%
c:\test>junk -N=1e6
foo frequency 5.885%
bar frequency 17.662%
baz frequency 23.446%
quux frequency 53.007%
####
#! perl -slw
use strict;
use List::Util qw[ sum ];
our $N ||= 1_000;
our $SCALE ||= 100;
sub pickGen {
my $total = sum @_;
my $accum = 0;
my @weights = map{
my $fencepost = $_[ $_ ] * $SCALE / $total;
( ( $_ ) x $fencepost, $accum += $fencepost )
} 0 .. $#_;
return sub {
my $randValue = rand $SCALE;
my $index = $weights[ $randValue ];
return $index if $index == int $index;
return $weights[ int( $randValue + ( $randValue <=> $index ) ) ]
};
}
my @array = (
["foo", 1],
["bar", 3],
["baz", 4],
["quux", 9]
);
my $picker = pickGen( map $_->[1], @array );
my %choices;
$choices{ $array[ $picker->() ][ 0 ] }++ for 1 .. $N;
printf "%10s frequency %.3f%%\n", $_, $choices{ $_ } *100 / $N
for sort{ $choices{ $a } <=> $choices{ $b } } keys %choices;