Robert Klemme
5/19/2006 3:39:00 PM
Robo wrote:
> I got the following piece of perl code, and trying to convert it to Ruby.
>
> I THINK what it's doing is from an array of floats, it has to select a
> random element, where the larger values have more chance of getting
> selected. So if weights = [0.2, 0.5, 0.1, 0.3], there'll be a higher
> chance of the method returning index 1 (0.5).
>
> Don't take my word only though...that's all I can make out of it. In
> particular the line I don't get is $sample = $i if rand $count [$i];
>
> Robo
>
> # Function to sample from an array of weighted elements
> # originally written by Abigail <abigail@foad.org>
> sub sample
> {
> # get the reference to the weights array
> my $weights = shift @_ or return undef;
> # internal counting variables
> my ($count, $sample);
>
> for (my $i = 0; $i < scalar @$weights; $i ++)
> {
> $count += $weights->[$i];
> $sample = $i if rand $count [$i];
> }
>
> # return an index into the weights array
> return $sample;
> }
def calc(weights)
r = weights.inject(0){|s,x|s+x} * rand
weights.inject(0) {|s,x| s+=x; return x if s>=r;s}
weights[-1]
end
>> 1_000_000.times { stat[ calc([0.2, 0.5, 0.1, 0.3]) ] += 1 }
=> 1000000
>> stat.each {|k,v| printf "%4.2f %4.2f\n", k, v/1_000_000.0}
0.20 0.18
0.30 0.27
0.10 0.09
0.50 0.45
=> {0.2=>182062, 0.3=>272793, 0.1=>90784, 0.5=>454361}
Kind regards
robert