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

7 thoughts on “The FizzBuzz Kata in Clojure

  1. and for the second part

    (defn has-char? [c st]
    (not (not-any? #(= % c) st)))

    (defn fizz? [n]
    (or (= (mod n 3) 0)
    (has-char? \3 (str n))))

    (defn buzz? [n]
    (or (= (mod n 5) 0)
    (has-char? \5 (str n))))

    (defn fizzbuzz [n]
    (cond
    (and (fizz? n)
    (buzz? n))
    “FizzBuzz”
    (fizz? n)
    “Fizz”
    (buzz? n)
    “Buzz”
    :default n))

    (println
    (map fizzbuzz (range 1 100)))

  2. here’s another :)

    (defn fizzbuzz [n]
    (cond
    (and (= (mod n 3) 0)
    (= (mod n 5) 0))
    “FizzBuzz”
    (= (mod n 3) 0)
    “Fizz”
    (= (mod n 5) 0)
    “Buzz”
    :default n))

    (println
    (map fizzbuzz (range 1 100)))

  3. (defn fizzbuzz [xs]
    (map #(str (when (= 0 (mod % 3)) “fizz”) (when (= 0 (mod % 5)) “buzz”)) xs))

  4. Here is my attempt.

    (defn fizz-buzz [lst]
    (letfn [(fizz? [n] (= (mod n 3) 0))
    (buzz? [n] (= (mod n 5) 0))]
    (let [f “Fizz”
    b “Buzz”
    items (map (fn [n]
    (cond (and (fizz? n) (buzz? n)) (str f b)
    (fizz? n) f
    (buzz? n) b
    :else n))
    lst)]
    (doseq [item items] (println item)))))

    • Hmm let me try format comment again.

      (defn fizz-buzz [lst]
        (letfn [(fizz? [n] (= (mod n 3) 0))
      	  (buzz? [n] (= (mod n 5) 0))]
          (let [f     "Fizz" 
      	  b     "Buzz" 
      	  items (map (fn [n]
      		       (cond (and (fizz? n) (buzz? n)) (str f b)
      			     (fizz? n) f
      			     (buzz? n) b
      			     :else n))
      		     lst)]
            (doseq [item items] (println item)))))
      

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s