#! 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;