use strict; use warnings; use Data::Dump qw/pp dd/; my %vote = ( alligator => 100, bear => 90, cat => 80, jellyfish => 10 ); my $N =0; $N += $_ for values %vote; # --- invert by division, proportion of non-voters my $N2 = 0; my %vote2 = map { my $v2 = 1/$vote{$_}; $N2 += $v2; $_ => $v2 } keys %vote; # --- invert by subtraction, number of non-voters my $N3 = 0; my %vote3 = map { my $v3 = $N-$vote{$_}; $N3 += $v3; $_ => $v3 } keys %vote; my (%dist1,%dist2,%dist3); my $e=5; $dist1{pick($N,\%vote)}++ for 1..10**$e; $dist2{pick($N2,\%vote2)}++ for 1..10**$e; $dist3{pick($N3,\%vote3)}++ for 1..10**$e; pp \%dist1,\%dist2,\%dist3; sub pick { my ($N,$h_vote)=@_; my @deb; my $r =rand($N); push @deb,$r; scalar keys %$h_vote; # reset each while ( my ($k,$v) = each %$h_vote) { $r -= $v; push @deb,[$r,$k,$v]; return $k if $r <=0; } die "ERROR", pp \@deb; }