use List::Util qw(first sum); use constant TRIALS => 1e6; sub prob_choice_picker { my %options = @_; my ($n, @a) = 0; while (my ($k,$v) = each %options) { $n += $v; push @a, [$n, $k]; } return sub { my $r = rand; ( first {$r <= $_->[0]} @a )->[1]; }; } my %ps = (aleph => 1/5, beth => 1/6, gimel => 1/7, daleth => 1/8, he => 1/9, waw => 1/10, zayin => 1/11); $ps{heth} = 1 - sum values %ps; my $picker = prob_choice_picker %ps; my %results; for (my $n = 0 ; $n < TRIALS ; ++$n) { ++$results{$picker->()}; } print "Event Occurred Expected Difference\n"; foreach (sort {$results{$b} <=> $results{$a}} keys %results) { printf "%-6s %f %f %f\n", $_, $results{$_}/TRIALS, $ps{$_}, abs($results{$_}/TRIALS - $ps{$_}); }