Last active
August 29, 2015 14:24
-
-
Save pqnelson/0f2dd93099635802a05e to your computer and use it in GitHub Desktop.
Expected runs for number of successful plays in a half-inning
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns half-inning) | |
(defn- int->play [i] | |
(let [i (mod i 5)] | |
(condp = i | |
0 :BB | |
1 :H1 | |
2 :H2 | |
3 :H3 | |
4 :HR))) | |
(defn- probability-for-play [play] | |
(condp = play | |
:BB 78/350 | |
:H1 212/350 | |
:H2 33/350 | |
:H3 7/350 | |
:HR 20/350 | |
(Error. (str "Unknown play: " play)))) | |
;; Based on the 2014 team averages | |
(defn- accurate-probability-for-play [play] | |
(condp = play | |
:BB 86/315 | |
:H1 157/315 | |
:H2 44/315 | |
:H3 1/63 | |
:HR 23/315 | |
(Error. (str "Unknown play: " play)))) | |
(defn cartesian-product [& lists] | |
(condp = (count lists) | |
0 nil | |
1 (map vector (first lists)) | |
(->> lists | |
(reduce #(for [x %1 y %2] [x y])) | |
(map flatten)))) | |
(defn all-possible-plays [n-plays] | |
(map vec (apply cartesian-product (repeat n-plays | |
(map int->play (range 5)))))) | |
;; given the state, i.e., the runner configuration, plus the play performed | |
;; return the new state and the runs scored | |
(defn perform [state play] | |
(condp = play | |
:BB [[1 (if (= 1 first-base) | |
1 | |
second-base) | |
(if (and (= 1 first-base) | |
(= 1 second-base)) | |
1 | |
third-base)] | |
(if (and (= 1 first-base) | |
(= 1 second-base) | |
(= 1 third-base)) | |
1 | |
0)] | |
:H1 [[1 (first state) 0] (reduce + (take-last 2 state))] | |
:H2 [[0 1 (first state)] (reduce + (take-last 2 state))] | |
:H3 [[0 0 1] (reduce + state)] | |
:HR [[0 0 0] (reduce + 1 state)] | |
(Error. (str "Unknown play: " play)))) | |
(defn- update-half-inning [[state runs-scored] play-performed] | |
(let [[new-state new-points] (perform state play-performed)] | |
[new-state (+ runs-scored new-points)])) | |
;; returns [new-base-config, runs-scored] | |
(defn runs-for-half-inning [plays-performed] | |
(last | |
(reduce update-half-inning | |
[[0 0 0] 0] | |
plays-performed))) | |
;; You can double check the probabilities work by computing | |
;; (every? #(= 1N (reduce + (map probability-for-plays (all-possible-plays %)))) (range 1 7)) | |
(defn probability-for-plays [plays-performed] | |
(reduce * (map probability-for-play plays-performed))) | |
(defn- expected-runs-for-half-inning [plays-performed] | |
(* (probability-for-plays plays-performed) | |
(runs-for-half-inning plays-performed))) | |
(defn expected-runs-for-number-of-plays [number-of-plays] | |
(reduce + | |
(map expected-runs-for-half-inning | |
(all-possible-plays number-of-plays)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment