#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $num_dice = 5; my @probabilities = ( 0.05, 0.10, 0.20, 0.30, 0.35 ); my @values = ( 1, 5, 7, 13, 17 ); my $throw_die_ntimes = 5; my @possibilities = (); my $it = combo($num_dice, 0 .. $num_dice-1); while (my $t = &$it()) { $possibilities[ttl($t)] += prob($t); } my $cum=0; for my $ttl (0 .. $#possibilities) { next if ! defined $possibilities[$ttl]; $cum += $possibilities[$ttl]; printf "% 5u prob=%.8f, prob<=:%.8f, prob>:%.8f\n", $ttl, $possibilities[$ttl], $cum, 1-$cum; } sub prob { my $prob=1; $prob *= $probabilities[$_] for @{$_[0]}; return $prob; } sub ttl { my $total=0; $total += $values[$_] for @{$_[0]}; return $total; } sub combo { my ($num_dice, @list) = @_; my @position = ($#list) x $num_dice; my $done_fl = 0; # Since we pre-decrement, adjust so we return proper item on first pass $position[0]++; return sub { return undef if $done_fl; my $cur = 0; { if (--$position[$cur] < 0) { # reset current dig & try next one $position[$cur] = $#list; $cur++; if ($cur > $num_dice) { $done_fl=1; return undef; } redo; } } return [ @list[@position] ]; } }