#!/usr/bin/python import sys import random debug = False def fact(n): if n == 0: return 1 return n * fact(n - 1) success_odds_by_dice = {} def get_odds(num_dice, indent = 0): global debug, success_odds_by_dice def iprint(val, *args): if debug: print (indent * " ") + str(val).format(*args) if num_dice == 0: return 1 iprint("-- get_odds({}) --", num_dice) if num_dice in success_odds_by_dice: iprint("-- odds: {} --", success_odds_by_dice[num_dice]) return success_odds_by_dice[num_dice] total_odds_success = 0 num_rolls = pow(6, num_dice) iprint("num rolls with {} dice: {:,}", num_dice, num_rolls) for i in xrange(1, num_dice + 1): remaining_dice = num_dice - i num_rolls_with_i_sixes = pow(5, remaining_dice) * fact(num_dice) / (fact(remaining_dice) * fact(i)) for j in xrange(i + 1, num_dice + 1): num_rolls_with_i_sixes iprint(" num rolls of {} dice with {} six(es): {:,}", num_dice, i, num_rolls_with_i_sixes) odds_i_sixes = num_rolls_with_i_sixes / float(num_rolls) iprint(" odds of that happening: {}", odds_i_sixes) total_odds_success += get_odds(num_dice - i, indent + 3) * odds_i_sixes success_odds_by_dice[num_dice] = total_odds_success iprint("-- odds: {} --", total_odds_success) return total_odds_success def get_monte_carlo_odds(iterations, num_dice): global debug successes = 0 for i in xrange(0, iterations): dice_left = num_dice while dice_left > 0: num_sixes = 0 for j in xrange(0, dice_left): if random.randint(1, 6) == 6: num_sixes += 1 if num_sixes == 0: dice_left = 0 else: dice_left -= num_sixes if dice_left == 0: successes += 1 if debug: print "-- monte carlo: {:,} / {:,} --".format(successes, iterations) return successes / float(iterations) def find_flag(flag): if flag in sys.argv: sys.argv.remove(flag) return True return False debug = find_flag("debug") simple_output = find_flag("simple") do_monte_carlo = not simple_output and not find_flag("no_mc") dice = int(sys.argv[1]) odds = get_odds(dice) monte_carlo_iters = 100000 if len(sys.argv) > 2: monte_carlo_iters = int(sys.argv[2]) if do_monte_carlo: monte_carlo_odds = get_monte_carlo_odds(monte_carlo_iters, dice) if debug: # extra line to separate debug output print if simple_output: print odds else: odds_str = "odds of getting donuts with {} dice: {:.2}%".format(dice, odds * 100) if do_monte_carlo: odds_str += ", monte carlo with {:,} iterations gives: {:.2}%".format(monte_carlo_iters, monte_carlo_odds * 100) print odds_str