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