in reply to Weighted random selection
A simple and efficient method is to build an array of items to pick where each item is replicated the number of times to match it's weighting. (Note: I factored the weights by 5 as that reduces the size of the array.);
Then you just pick (once!) from that array and your guaranteed to get darn close to your chosen weightings:
#! perl -slw use strict; use List::Util qw[ sum ]; our $N ||= 1e3; my %group = ( ad1 => 1, ad2 => 2, ad3 => 4 ); my $t = sum values %group; print "Expected"; for ( sort keys %group ) { printf "$_ to be chosen %f%%\n", $group{ $_ } / $t * 100; } my( $key, $value, @choices ); push @choices, ($key) x $value while ( $key, $value ) = each %group; my %picks; for ( 1.. $N ) { $picks{ @choices[ rand @choices ] } ++; } print "\nActual"; for ( sort keys %picks ) { printf "$_ chosen %f%%\n", $picks{ $_ } / $N * 100; } __END__ C:\test>700683 -N=1e6 Expected ad1 to be chosen 14.285714% ad2 to be chosen 28.571429% ad3 to be chosen 57.142857% Actual ad1 chosen 14.276200% ad2 chosen 28.601600% ad3 chosen 57.122200% C:\test>700683 -N=1e6 Expected ad1 to be chosen 14.285714% ad2 to be chosen 28.571429% ad3 to be chosen 57.142857% Actual ad1 chosen 14.309300% ad2 chosen 28.577100% ad3 chosen 57.113600%
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Weighted random selection
by cosmicperl (Chaplain) on Jul 28, 2008 at 23:58 UTC | |
by BrowserUk (Patriarch) on Jul 29, 2008 at 00:57 UTC | |
by JavaFan (Canon) on Jul 29, 2008 at 11:31 UTC | |
by BrowserUk (Patriarch) on Jul 29, 2008 at 12:31 UTC |