Skip to content

Instantly share code, notes, and snippets.

@pqnelson
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pqnelson/0f2dd93099635802a05e to your computer and use it in GitHub Desktop.
Save pqnelson/0f2dd93099635802a05e to your computer and use it in GitHub Desktop.
Expected runs for number of successful plays in a half-inning
(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