sub pickAll{
my @weights = @_;
my $total = sum @weights;
my @order;
for( 0 .. $#_ ) {
my $pick = pick( \@weights, $total );
push @order, $pick;
$total -= $weights[ $pick ];
$weights[ $pick ] = 0;
}
return @order;
}
####
#! perl -slw
use strict;
use List::Util qw[ sum ];
our $SHIPS ||= 10;
our $REPS ||= 1e5;
sub pick {
my( $weights, $total ) = @_;
my $rand = rand $total;
( $rand -= $weights->[ $_ ] ) < 0
and return $_ for 0 .. $#$weights;
}
sub pickAll{
my @weights = @_;
my $total = sum @weights;
my @order;
for( 0 .. $#_ ) {
my $pick = pick( \@weights, $total );
push @order, $pick;
$total -= $weights[ $pick ];
$weights[ $pick ] = 0;
}
return @order;
}
my @weights = map rand( 16 ), 1 .. $SHIPS;
print "$_ : $weights[ $_ ]" for 0 .. $#weights;
my $total = sum @weights;
print "\n";
print join ' ', pickAll( @weights ) for 1 .. $REPS;
####
C:\test>WeightedPick.pl -SHIPS=4 -REPS=30
0 : 14.4176797792315
1 : 1.80334489420056
2 : 14.493153475225
3 : 14.258566647768
3 2 0 1
3 0 2 1
0 3 2 1
0 3 1 2
0 3 2 1
0 2 3 1
3 2 0 1
0 2 3 1
3 0 2 1
1 0 3 2
3 2 0 1
3 0 2 1
0 3 2 1
3 0 2 1
3 0 2 1
0 2 3 1
3 1 2 0
2 3 0 1
2 0 3 1
3 2 0 1
0 3 2 1
2 3 0 1
3 0 2 1
3 2 0 1
2 3 0 1
2 3 1 0
3 0 2 1
0 2 1 3
3 2 0 1
0 2 3 1
####
C:\test>WeightedPick.pl -SHIPS=4 -REPS=30
0 : 0.762649480253458
1 : 10.0145217105746
2 : 6.81761548668146
3 : 15.7317210100591
1 3 2 0
1 2 3 0
2 1 3 0
3 1 2 0
3 2 1 0
2 1 3 0
3 1 2 0
1 3 2 0
3 1 2 0
1 2 3 0
1 3 2 0
1 3 2 0
3 1 2 0
1 3 2 0
1 3 2 0
2 1 3 0
2 3 1 0
1 3 2 0
3 1 2 0
2 3 1 0
2 3 1 0
1 2 3 0
3 1 2 0
3 1 2 0
2 3 1 0
3 1 2 0
2 3 1 0
1 3 0 2
3 1 2 0
3 1 2 0