The FizzBuzz Kata in Clojure

My first Clojure code was the Bowling Kata I wrote about in my last post. Today I did the FizzBuzz Kata and the stage 2 requirements. This was a lot simpler than the Bowling Kata.

There is not much to say about it, here is my test code:

(ns fizzbuzztest
 (:use fizzbuzz clojure.test))

(deftest nonefizzbuzz-numbers-return-itself
 (is (= (fizzbuzz '(1 2 4 7)) '(1 2 4 7))))

(deftest multiple-of-three-and-not-five-return-fizz
 (is (= (fizzbuzz '(3 6 9 12 18 21 24 27)) (take 8 (repeat "fizz")) )))

(deftest multiple-of-five-and-not-three-return-buzz
 (is (= (fizzbuzz '(5 10 20 25 40 50 55 65)) (take 8 (repeat "buzz")) )))

(deftest multiple-of-three-and-five-return-fizzbuzz
 (is (= (fizzbuzz '(15 30 45 60 75 90 105 120)) (take 8 (repeat "fizzbuzz")) )))

(deftest three-in-number-returns-fizz
 (is (= (fizzbuzz '(3 13 23 31 103)) (repeat 5 "fizz"))))

(deftest five-in-number-returns-buzz
 (is (= (fizzbuzz '(5 52 58 151 502)) (repeat 5 "buzz"))))

(run-tests)

and here is the implementation:

(ns fizzbuzz)

(defn- numeric-fizz? [n]
 (= (rem n 3) 0))

(defn- string-fizz? [n]
 (some #(= % \3) (str n)))

(defn- fizz? [n]
 (or (numeric-fizz? n) (string-fizz? n)))

(defn- numeric-buzz? [n]
 (= (rem n 5) 0))

(defn- string-buzz? [n]
 (some #(= % \5) (str n)))

(defn- buzz? [n]
 (or (numeric-buzz? n) (string-buzz? n)))

(defn- fizzbuzz? [n]
 (and (fizz? n) (buzz? n)))

(defn- replace-fizz-buzz [n]
 (cond
 (fizzbuzz? n) "fizzbuzz"
 (fizz? n) "fizz"
 (buzz? n) "buzz"
 (number? n) n))

(defn fizzbuzz [numbers]

 (map replace-fizz-buzz numbers))

I like the function that checks if a number contains a ‘3’ character. Although it looks weird it is not so hard to read after  getting a little used to Clojure code.

(defn- string-fizz? [n]
 (some #(= % \3) (str n)))

This functions gets a number n as parameter, which is converted to a string with (str n). The some calls the anonymous function #(= % \3) on each element (i.e. character) of n as string. If the anonymous function returns true, some return true as well. The anonymous function simply checks if its parameter (the %) is the character 3.

There is one issue with the cond in replace-fizz-buzz:the last condition (number? n) is just a dummy condition. Actually I don’t want it. If none of the other conditions match, it should just return the n. But that is not possible with cond. I’m looking for a better solution…

I also created my first Leiningen build script to run the tests. Leiningen is a build tool for Clojure. Here is the build script (named project.clj and placed in the project root folder):


(defproject fizzbuzz "1.0.0"
 :description "A cloure implmementation of the FizzBuzz kata."
 :dependencies [[org.clojure/clojure "1.1.0"]])

Quite simple ;-)

Running the following command:

$ lein test fizzbuzztest

prints:

 [null] Testing fizzbuzztest
 [null] Ran 6 tests containing 6 assertions.
 [null] 0 failures, 0 errors.
 [null] --------------------
 [null] Total:
 [null] Ran 6 tests containing 6 assertions.
 [null] 0 failures, 0 errors.

Works, but I have no idea, why it prints the [null] stuff.

Advertisements