Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
bowling.clj
(ns bowling.core-spec
(:require [speclj.core :refer :all]))
(def all-pins 10)
(def frames-per-game 10)
(defn game-over [frame] (= frame frames-per-game))
(defn strike-score [rolls] (+ all-pins (nth rolls 1) (nth rolls 2)))
(defn spare-score [rolls] (+ all-pins (nth rolls 2)))
(defn frame-score [rolls] (+ (first rolls) (second rolls)))
(defn is-strike [rolls] (= all-pins (first rolls)))
(defn is-spare [rolls] (= all-pins (frame-score rolls)))
(defn bowl [rolls]
(loop [rolls rolls
frame 0
score 0]
(if (game-over frame)
score
(cond
(is-strike rolls)
(recur (rest rolls)
(inc frame)
(+ score (strike-score rolls)))
(is-spare rolls)
(recur (rest (rest rolls))
(inc frame)
(+ score (spare-score rolls)))
:else
(recur (rest (rest rolls))
(inc frame)
(+ score (frame-score rolls)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn roll-many [times pins]
(take times (cycle [pins])))
(describe "gutter game"
(it "scores zero points"
(let [gutter-game (roll-many 20 0)]
(should= 0 (bowl gutter-game)))))
(describe "all ones"
(it "scores one point per throw"
(let [all-ones (roll-many 20 1)]
(should= 20 (bowl all-ones)))))
(describe "spare"
(it "counts the next roll as a bonus"
(let [game (concat [4 6 3 1] (roll-many 16 0))]
(should= (+ 4 6 3 3 1)
(bowl game)))))
(describe "strike"
(it "counts the next two rolls as a bonus"
(let [game (concat [10 3 4 1] (roll-many 15 0))]
(should= (+ 10 3 4 3 4 1)
(bowl game)))))
(describe "perfection"
(it "should score 300"
(let [game (roll-many 12 10)]
(should= 300 (bowl game)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment