More Clojure from Uncle Bob JSPS

Posted by Uncle Bob on 07/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

Leave a response