Skip to content

Instantly share code, notes, and snippets.

@madstap
Last active April 21, 2021 23:49
Show Gist options
  • Save madstap/d9eb24395841f5a2ee2292ccbd0baec4 to your computer and use it in GitHub Desktop.
Save madstap/d9eb24395841f5a2ee2292ccbd0baec4 to your computer and use it in GitHub Desktop.
Bowling kata
(ns bowling)
(def empty-state
{:frames []
:current-frame []
:score 0
:strike-counter 0
:spare-counter 0})
(defn dec-zero [n]
(max 0 (dec n)))
(defn roll [{:keys [frames current-frame strike-counter spare-counter score] :as state}
pins]
(let [last-frame? (= 9 (count frames)) ; TODO: Bunch of rules about the last frame
strike? (and (empty? current-frame) (= 10 pins))
spare? (and (seq current-frame) (= 10 (+ (first current-frame) pins)))
new-score (cond-> (+ score pins)
(or (pos? strike-counter)
(pos? spare-counter))
(+ pins))
frame-ended? (or strike? (seq current-frame))]
(-> state
(assoc :score new-score)
(update :strike-counter dec-zero)
(update :spare-counter dec-zero)
(cond-> strike? (assoc :strike-counter 2)
spare? (assoc :spare-counter 1)
frame-ended? (-> (update :frames conj (conj current-frame pins))
(assoc :current-frame []))
(not frame-ended?) (update :current-frame conj pins)))))
(defn game [rolls]
(reduce roll empty-state rolls))
(defn dbg [rolls]
(map #(assoc %1 :pins %2) (rest (reductions roll empty-state rolls)) rolls))
(comment
;; The example from the description
(= 48 (:score (game [10 5 5 9 0])))
;; Debug what is happening at each step
(dbg [10 5 5 9 0])
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment