#!/usr/bin/env perl use 5.010; 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; say "Vote"; show(\%vote, 1); # --- invert by exponentiation for my $C ( 0.9, 0.95, 0.96, 0.97, 0.98, 0.99) { my $N4=0; my %vote4 = map { my $v4 = $C ** $vote{$_}; $N4 += $v4; $_ => $v4; } keys %vote; my %dist4; my $e=5; $dist4{pick($N4,\%vote4)}++ for 1..10**$e; say "C=$C"; show( \%dist4, -1); } sub show { # show counts and percentages my $href = shift; my $dir = shift; # sort direction 1=ascending, -1=descending my $tot=0; $tot += $_ for values %$href; for my $k (sort {$dir * ($a cmp $b)} keys %$href) { printf "%s => %5d (%5.2f%%) ", $k, $href->{$k}, 100*($href->{$k}/$tot); } say ''; } 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; }