Right you are. Putting the possible combinations into play, I finally came up with a program that gets the right answer, and can be used for any number of sides (though I did not generalize it to be any number of dice, nor any number of discards -- it is possible to do so, but it's messy enough already). For 6 sided dice, it is probably working harder than the explicit method, but for 20 sided dice, it is much faster.
In the code, L is the low value for the roll. The number of distinct permutations possible varies, depending on how many times L is repeated, and the average value for the permutations also changes based on that.
my $sides = 16;
my ($total, $rolls) = (0,0);
foreach my $L (1..$sides) {
# Start with all others = $L
my $combos = 1;
my $sum = $L * 3;
$rolls += $combos;
if ($sides > $L) {
# How many repeat $L twice, with one higher?
$combos = 4 * ($sides-$L);
my $avg = 2 * $L + ($L+1+$sides)/2;
$rolls += $combos;
$sum += $avg * $combos;
# How many repeat $L once, with two higher?
$combos = 6 * ($sides-$L)**2;
$avg = $L + ($L+1+$sides);
$rolls += $combos;
$sum += $avg * $combos;
# How many do not repeat $L?
$combos = 4 * ($sides-$L)**3;
$avg = 3*($L+1+$sides)/2;
$rolls += $combos;
$sum += $avg * $combos;
}
printf "%d combos of three dice >= $L averaging %g\n", $combos, $sum
+/$combos;
$total += $sum;
}
printf "Average of $rolls rolls is %g\n", $total/$rolls;
# Explicit method included for check
$sum = $rolls = 0;
for $i (1..$sides) {
for $j (1..$sides) {
for $k (1..$sides) {
for $l (1..$sides) {
my $min = $l;
for ($i, $j, $k) { $min = $_ if $_ < $min }
$sum += $i + $j + $k + $l - $min;
++$rolls;
}
}
}
}
printf "Average of $rolls rolls is %g\n", $sum/$rolls;
The PerlMonk tr/// Advocate
| [reply] [d/l] |