in reply to
Re^4: Monte Carlo - Coin Toss

in thread Monte Carlo - Coin Toss

repellent:

Sweet! So of course I had to take another look:

`sub pascal_tri_row {
my $r = shift;
return () if $r < 0;
my @row = (1) x ($r + 1);
for my $i (1 .. $r - 1)
{
$row[$_] += $row[$_ - 1]
for reverse 1 .. $i;
}
return @row;
}
sub robo_2 {
my $row = shift;
my @cols = (1);
++$row;
$cols[$_] = $cols[$_-1] * ($row-$_)/$_ for 1 .. $row-1;
return @cols;
}
sub triangle {
my $numTosses = shift;
my @triangle = (0, 1, 0);
for (1 .. $numTosses) {
my @newTriangle=(0);
push @newTriangle, $triangle[$_]+$triangle[$_+1] for 0 .. $#tr
+iangle-1;
push @newTriangle, 0;
@triangle = @newTriangle;
}
return @triangle[1..$#triangle-1];
}
use Benchmark qw(cmpthese);
print "robo_1: ", join(" ",triangle(8)), "\n";
print "repel1: ", join(" ",pascal_tri_row(8)), "\n";
print "robo_2: ", join(" ",robo_2(8)), "\n";
cmpthese -1, {
robo_tri => sub { triangle(32) },
repel_tri => sub { pascal_tri_row(32) },
robo_2 => sub { robo_2(32) },
};
`

First I put in a trace so I could be sure I wasn't generating useless values. Next, I couldn't bear the zeroes you had to add to your function to match my original return value. They were just sentinel values to simplify the calculation, anyway. So I fixed the original to return only the values of interest. Finally, I had to squeeze a little more speed out of it:

`$ perl 892898.pl
robo_1: 1 8 28 56 70 56 28 8 1
repel1: 1 8 28 56 70 56 28 8 1
robo_2: 1 8 28 56 70 56 28 8 1
Rate robo_tri repel_tri robo_2
robo_tri 2196/s -- -42% -93%
repel_tri 3775/s 72% -- -88%
robo_2 31946/s 1355% 746% --
`

You should've read a bit further down in the wikipedia article you linked. It had a much better algorithm for calculating the coefficients of any row. It saved a nested loop.

;^)

...roboticus

*When your only tool is a hammer, all problems look like your thumb.*