in reply to Rolling DND Dice.
Suggestions for how to make this smaller and Perlisher are welcome. I'm sure this can be compressed to a one-liner, somehow...
Heres my go at a generic version. Returns the average of NdS Drop X. N,S should be larger than 0 and X non-negative. eg: avg_die(4,6,1) gives your result (in 162 chars, including sub decl. :-)
#!perl -l use strict; use warnings; $|++; #162 chars, including sub decl. sub A{my($d,$s,$l,$y,$c,$t,$z)=@_;$c||=\$z;if(!$d){ $t+=$_ for(sort{$a<=>$b}@$y)[$l..$#$y];$$c++}else{$t+=A ($d-1,$s,$l,[@{$y||[]},$_],$c)for 1..$s}$y?$t:$t/$z}
sub avg_roll{ my($num_dice, $sides_of_dice, $num_to_lose, # We only expect the below to be provided when called # recursively $rolled_ref, $counter_ref)=@_; my ($total,$counter); # we declare these with the @_ in the golf # version here we seperate them to show they # arent really parameters. $counter_ref||=\$counter; # make a reference to our counter, # unless we were called recursively; unless ($num_dice){ # we are done, no more dice $total+=$_ # increment the total by the value of the dice for ( sort {$a<=>$b} @$rolled_ref # sort the results numerica +lly # to make avg_roll(4,12,1) +work. )[$num_to_lose..$#$rolled_ref]; # take a slice $$counter_ref++ # incrememnt the counter } else { # we havent finished rolling $total+= # so increment the total avg_roll( # by the result $num_dice-1, # of the next die $sides_of_dice, $num_to_lose, [ # pass in a ref, @{$rolled_ref||[]}, # containing the previous rolls $_ # and the new one ], $counter_ref # and a way to access the counter ) for 1..$sides_of_dice # for each possible roll of the d +ie } $rolled_ref ? $total # if we are not the root of the r +ecursion # return the total, whatever it m +ay be : $total/$counter # return the average. }
print A(4,6,1); print avg_roll(4,6,1); __END__ 12.2445987654321 12.2445987654321
Update: 150 chars.
sub B{my($d,$s,$l,$c,@y,$t,$z)=@_;$c||=\$z;if(!$d){$t+=$_ for(sort{$a<=>$b}@y)[$l..$#y];$$c++}else{$t+=B($d-1,$s,$l, $c,@y,$_)for 1..$s}@y?$t:$t/$z}
:-)
First they ignore you, then they laugh at you, then they fight you, then you win.
-- Gandhi
|
|---|