{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Dice Baseball\n", "\n", "The [538 Riddler for March 22, 2019](https://fivethirtyeight.com/features/can-you-turn-americas-pastime-into-a-game-of-yahtzee/) asks us to simulate baseball using probabilities from a 19th century dice game called *Our National Ball Game*:\n", "\n", " 1,1: double 2,2: strike 3,3: out at 1st 4,4: fly out\n", " 1,2: single 2,3: strike 3,4: out at 1st 4,5: fly out\n", " 1,3: single 2,4: strike 3,5: out at 1st 4,6: fly out\n", " 1,4: single 2,5: strike 3,6: out at 1st 5,5: double play\n", " 1,5: base on error 2,6: foul out 5,6: triple\n", " 1,6: base on balls 6,6: home run\n", "\n", "\n", "The rules left some things unspecified; the following are my current choices (in an early version I made different choices that resulted in slightly more runs):\n", "\n", "* On a* b*-base hit, runners advance* b* bases, except that a runner on second scores on a 1-base hit.\n", "* On an \"out at first\", all runners advance one base.\n", "* A double play only applies if there is a runner on first; in that case other runners advance.\n", "* On a fly out, a runner on third scores; other runners do not advance.\n", "* On an error all runners advance one base. \n", "* On a base on balls, only forced runners advance.\n", "\n", "I also made some choices about the implementation:\n", "\n", "- Exactly one outcome happens to each batter. We call that an *event*.\n", "- I'll represent events with the following one letter codes:\n", " - `K`, `O`, `o`, `f`, `D`: strikeout, foul out, out at first, fly out, double play\n", " - `1`, `2`, `3`, `4`: single, double, triple, home run\n", " - `E`, `B`: error, base on balls\n", "- Note the \"strike\" dice roll is not an event; it is only part of an event. From the probability of a \"strike\" dice roll, I compute the probability of three strikes in a row, and call that a strikeout event. Sice there are 7 dice rolls giving \"strike\", the probability of a strike is 7/36, and the probability of a strikeout is (7/36)**3.\n", "- Note that a die roll such as `1,1` is a 1/36 event, whereas `1,2` is a 2/36 event, because it also represents (2, 1).\n", "- I'll keep track of runners with a list of occupied bases; `runners = [1, 2]` means runners on first and second.\n", "- A runner who advances to base 4 or higher has scored a run (unless there are already 3 outs).\n", "- The function `inning` simulates a half inning and returns the number of runs scored.\n", "- I want to be able to test `inning` by feeding it specific events, and I also want to generate random innings. So I'll make the interface be that I pass in an *iterable* of events. The function `event_stream` generates an endless stream of randomly sampled events.\n", "- Note that it is consider good Pythonic style to automatically convert Booleans to integers, so for a runner on second (`r = 2`) when the event is a single (`e = '1'`), the expression `r + int(e) + (r == 2)` evaluates to `2 + 1 + 1` or `4`, meaning the runner on second scores.\n", "- I'll play 1 million innings and store the resulting scores in `innings`.\n", "- To simulate a game I just sample 9 elements of `innings` and sum them.\n", "\n", "# The Code" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "import random" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def event_stream(events='2111111EEBBOOooooooofffffD334', strike=7/36):\n", " \"An iterator of random events. Defaults from `Our National Ball Game`.\"\n", " while True:\n", " yield 'K' if (random.random() < strike ** 3) else random.choice(events)\n", " \n", "def inning(events=event_stream(), verbose=False) -> int:\n", " \"Simulate a half inning based on events, and return number of runs scored.\"\n", " outs = runs = 0 # Inning starts with no outs and no runs,\n", " runners = [] # ... and with nobody on base\n", " for e in events:\n", " if verbose: print(f'{outs} outs, {runs} runs, event: {e}, runners: {runners}')\n", " # What happens to the batter?\n", " if e in 'KOofD': outs += 1 # Batter is out\n", " elif e in '1234EB': runners.append(0) # Batter becomes a runner\n", " # What happens to the runners?\n", " if e == 'D' and 1 in runners: # double play: runner on 1st out, others advance\n", " outs += 1\n", " runners = [r + 1 for r in runners if r != 1]\n", " elif e in 'oE': # out at first or error: runners advance\n", " runners = [r + 1 for r in runners]\n", " elif e == 'f' and 3 in runners and outs < 3: # fly out: runner on 3rd scores\n", " runners.remove(3)\n", " runs += 1\n", " elif e in '1234': # single, double, triple, homer\n", " runners = [r + int(e) + (r == 2) for r in runners]\n", " elif e == 'B': # base on balls: forced runners advance \n", " runners = [r + forced(runners, r) for r in runners]\n", " # See if inning is over, and if not, whether anyone scored\n", " if outs >= 3:\n", " return runs\n", " runs += sum(r >= 4 for r in runners)\n", " runners = [r for r in runners if r < 4]\n", " \n", "def forced(runners, r) -> bool: return all(b in runners for b in range(r))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Testing\n", "\n", "Let's peek at some random innings:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs, 0 runs, event: E, runners: []\n", "0 outs, 0 runs, event: 4, runners: [1]\n", "0 outs, 2 runs, event: E, runners: []\n", "0 outs, 2 runs, event: 1, runners: [1]\n", "0 outs, 2 runs, event: f, runners: [2, 1]\n", "1 outs, 2 runs, event: B, runners: [2, 1]\n", "1 outs, 2 runs, event: 1, runners: [3, 2, 1]\n", "1 outs, 4 runs, event: E, runners: [2, 1]\n", "1 outs, 4 runs, event: o, runners: [3, 2, 1]\n", "2 outs, 5 runs, event: o, runners: [3, 2]\n" ] }, { "data": { "text/plain": [ "5" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning(verbose=True)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs, 0 runs, event: 1, runners: []\n", "0 outs, 0 runs, event: B, runners: [1]\n", "0 outs, 0 runs, event: O, runners: [2, 1]\n", "1 outs, 0 runs, event: 1, runners: [2, 1]\n", "1 outs, 1 runs, event: 3, runners: [2, 1]\n", "1 outs, 3 runs, event: 1, runners: [3]\n", "1 outs, 4 runs, event: f, runners: [1]\n", "2 outs, 4 runs, event: o, runners: [1]\n" ] }, { "data": { "text/plain": [ "4" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning(verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we can feed in any events we want to test the code:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs, 0 runs, event: 2, runners: []\n", "0 outs, 0 runs, event: E, runners: [2]\n", "0 outs, 0 runs, event: B, runners: [3, 1]\n", "0 outs, 0 runs, event: B, runners: [3, 2, 1]\n", "0 outs, 1 runs, event: 1, runners: [3, 2, 1]\n", "0 outs, 3 runs, event: D, runners: [2, 1]\n", "2 outs, 3 runs, event: B, runners: [3]\n", "2 outs, 3 runs, event: 1, runners: [3, 1]\n", "2 outs, 4 runs, event: 2, runners: [2, 1]\n", "2 outs, 5 runs, event: f, runners: [3, 2]\n" ] }, { "data": { "text/plain": [ "5" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning('2EBB1DB12f', verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That looks good.\n", "\n", "# Simulating\n", "\n", "Now, simulate a million innings, and then sample from them to simulate a million nine-inning games (for one team):" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "N = 1000000\n", "innings = [inning() for _ in range(N)]\n", "games = [sum(random.sample(innings, 9)) for _ in range(N)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see histograms:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "