More Clojure from Uncle Bob JSPS

More Clojure from Uncle Bob JSPS

Posted by Uncle Bob on Friday, July 31, 2009

Thanks to all who posted their solutions to the Bowling Game. Just to be contrary, I decided to implement yet another kind of solution. This one clearly shows my OO roots.

h2. Here are the tests.

(ns bowling-game) (use 'clojure.contrib.test-is) (use 'bowling-game)  (defn roll-list [game list]   (vec (concat game list)))  (defn roll-many [game n pins]   (roll-list game (repeat n pins)))  (deftest can-create-game   (is (not (nil? (new-game)))))  (deftest gutter-game-should-score-0   (is (= 0 (score (-> (new-game) (roll-many 20 0))))))  (deftest all-ones-should-score-20   (is (= 20 (score (-> (new-game) (roll-many 20 1))))))  (deftest one-spare   (is (= 16 (score (-> (new-game) (roll-list [5 5 3]) (roll-many 17 0))))))  (deftest one_strike   (is (= 24 (score (-> (new-game) (roll-list [10 3 4]) (roll-many 16 0))))))  (deftest perfect-game   (is (= 300 (score (-> (new-game) (roll-many 12 10))))))  (run-tests 'bowling-game)

And here is the code.

(ns bowling-game) (defn new-game [] [])  (defn frame-type [[first second]]   (cond     (= 10 first) :strike     (= 10 (+ first second)) :spare     :else :no-mark))  (defmulti frame-size frame-type) (defmethod frame-size :strike [_] 1) (defmethod frame-size :spare [_] 2) (defmethod frame-size :no-mark [_] 2)  (defmulti frame-score frame-type) (defmethod frame-score :strike [[_ first second]] (+ 10 (+ first second))) (defmethod frame-score :spare [[_ _ next]] (+ 10 next)) (defmethod frame-score :no-mark [[first second]] (+ first second))  (defn score [game]   (loop [frame 1 rolls game score 0]     (if (> frame 10)       score       (recur (inc frame) (subvec rolls (frame-size rolls)) (+ score (frame-score rolls))))))

Comments