diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/odds.py b/odds.py new file mode 100755 index 0000000..6546045 --- /dev/null +++ b/odds.py @@ -0,0 +1,95 @@ +#!/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