# Pure Danger Tech home

# Clojure FizzBuzz

30 Jun 2011

Realized I had never done FizzBuzz in Clojure. FizzBuzz says for numbers 1 to 100,

• Print “Fizz” if number is a multiple of 3
• Print “Buzz” if number is a multiple of 5
• Print “FizzBuzz” if number is a multiple of both
• Otherwise, print the number

Here’s my (failing) test:

```(ns fizzbuzz
(:use [ clojure.test ]))

(defn fizzbuzz [upto]
"TODO")

(deftest test-fizzbuzz
(is (= [1 2 "Fizz" 4 "Buzz" "Fizz" 7 8 "Fizz" "Buzz" 11 "Fizz" 13 14 "FizzBuzz"]
(fizzbuzz 15))))
```

The most natural translation of requirement to code I could write:

```(defn fb [x]
(if (= 0 (mod x 3))
(if (= 0 (mod x 5))
"FizzBuzz"
"Fizz")
(if (= 0 (mod x 5))
"Buzz"
x)))

(defn fizzbuzz [upto]
(map fb (range 1 (inc upto))))
```

I don’t like those (= 0 (mod x n)) though. Rerwote with a mult-of function:

```(defn mult-of [x m]
(zero? (mod x m)))

(defn fb [x]
(if (mult-of x 3)
(if (mult-of x 5)
"FizzBuzz"
"Fizz")
(if (mult-of x 5)
"Buzz"
x)))
```

Better. That repeated (mult-of x 5) bugged me though. I really want to apply both mult-of 3 and mult-of 5 to x once. Added a new mult-say that checked if x is a multiple of n and if so returns what it should say, otherwise nil. Apply mult-say with 3 “Fizz” and 5 “Buzz” and combine the results into a string. If the string is empty, return x, otherwise the string.

```(defn mult-say [x n say]
(when (mult-of x n) say))

(defn fb [x]
(let [mults (str (mult-say x 3 "Fizz")
(mult-say x 5 "Buzz"))]
(if (empty? mults) x mults)))
```

Kind of bugs me that the 3 “Fizz” 5 “Buzz” stuff is encoded into the function. Why not have a general form of this that takes a specification of what multiples and what strings to print?

We’ll need to alter our test a bit to pass the specification as well as the code of course. Here’s the whole updated mess:

```(ns fizzbuzz
(:use [ clojure.test ]))

(defn mult-of [x m]
(zero? (mod x m)))

(defn mult-say [x n say]
(when (mult-of x n) say))

(defn fb [specs x]
(let [spec-fn (fn [[m say]] (mult-say x m say))
mults (apply str (map spec-fn specs))]
(if (empty? mults) x mults)))

(defn fizzbuzz [specs upto]
(map #(fb specs %) (range 1 (inc upto))))

(deftest test-fizzbuzz
(is (= [1 2 "Fizz" 4 "Buzz" "Fizz" 7 8 "Fizz" "Buzz" 11 "Fizz" 13 14 "FizzBuzz"]
(fizzbuzz {3 "Fizz" 5 "Buzz"} 15))))
```

And now we can also use fizz buzz to do alternate versions:

```fizzbuzz> (fizzbuzz {2 "bop" 3 "fizz" 5 "buzz"} 30)
(1 "bop" "fizz" "bop" "buzz" "bopfizz" 7 "bop" "fizz" "bopbuzz" 11 "bopfizz" 13 "bop"
"fizzbuzz" "bop" 17 "bopfizz" 19 "bopbuzz" "fizz" "bop" 23 "bopfizz" "buzz" "bop"
"fizz" "bop" 29 "bopfizzbuzz")
```