{{ message }}

Instantly share code, notes, and snippets.

# ericnormand/00 FizzBuzz.md

Last active Oct 6, 2020

FizzBuzz, but with no ifs

FizzBuzz is a classic interview exercise meant to filter out people who can't program. It tests that you can write conditionals, loops, and a basic modulo check for divisibility. While it seems kind of insulting to ask someone to solve such a trivial problem, imagine if the interviewee couldn't do it. It's a quick way to check for basic skill before wasting an hour in the interview.

This week, you're going to write FizzBuzz, but just to show off to the interviewer, you're not going to write any conditionals or loops. Just to be clear, that means no `if`, `when`, `cond`, or `case` expressions.

Here are the rules:

Write a function that is passed a sequence of integers.

For each integer, if it's divisible by 3, print "Fizz". If it's divisible by 5, print "Buzz". If it's divisible by both 3 and 5, print "FizzBuzz". Finally, if it's divisible by neither, print the number itself. Each printing should be on a separate line.

Email submissions to eric@purelyfunctional.tv before September 13, 2020. You can discuss the submissions in the comments below.

 (ns tst.demo.core (:use tupelo.core tupelo.test)) (defn div-3? [n] (zero? (rem n 3))) ; hidden `if` statement (defn div-5? [n] (zero? (rem n 5))) ; hidden `if` statement (defn fizzbuzz [n] (let [factors [(div-3? n) (div-5? n)] result (get {[true false] "Fizz" [false true] "Buzz" [true true] "FizzBuzz"} factors n)] ; default has hidden `if` result)) (dotest (is= [true false false true false false true] (mapv div-3? (thru -3 3))) (is= [true false false false false true false false false false true] (mapv div-5? (thru -5 5))) (is= ["FizzBuzz" -14 -13 "Fizz" -11 "Buzz" "Fizz" -8 -7 "Fizz" "Buzz" -4 "Fizz" -2 -1 "FizzBuzz" 1 2 "Fizz" 4 "Buzz" "Fizz" 7 8 "Fizz" "Buzz" 11 "Fizz" 13 14 "FizzBuzz"] (mapv fizzbuzz (thru -15 15))))
 (defn fizzbuzz [n] (let [fizzes (cycle ["" "" "Fizz"]) buzzes (cycle ["" "" "" "" "Buzz"]) pattern (map str fizzes buzzes) numbers (map str (rest (range)))] (take n (map #(some not-empty %&) pattern numbers)))) (doseq [x (fizzbuzz 100)] (println x))
 (defn fizzbuzz [xs] (let [x (first xs)] (and x (let [div-3 (= (mod x 3) 0) div-5 (= (mod x 5) 0)] (and div-3 (print "Fizz")) (and div-5 (print "Buzz")) (and (not div-3) (not div-5) (print x)) (println) (recur (rest xs))))))
 (defn fizzbuzz [ns] (doseq [n ns] (prn (get {[0 nil] "Fizz" [nil 0] "Buzz" [0 0] "FizzBuzz"} [(get {0 0} (rem n 3)) (get {0 0} (rem n 5))] n))))
 (ns clojure-challenge.issue-394) (defn fizzbuzzer [x] (or (and (= 0 (mod x 15)) "fizzbuzz") (and (= 0 (mod x 5)) "buzz") (and (= 0 (mod x 3)) "fizz") (str x))) (defn -main "Main function" [] (println (->> (range 31) (map fizzbuzzer))))
 (defn fizzbuzz [n] (letfn [(f [[div s]] (and (zero? (mod n div)) s))] (or (some f [[15 "FizzBuzz"] [5 "Buzz"] [3 "Fizz"]]) n))) (defn print-fizzbuzz [ns] (dorun (map (comp println fizzbuzz) ns)))
 ;; First solution (defn fizz-buzz-or-number [x] ( ["FizzBuzz" x x "Fizz" x "Buzz" "Fizz" x x "Fizz" "Buzz" x "Fizz" x x] (mod x 15))) (defn fizz-buzz [xs] (doseq [x (map fizz-buzz-x xs)] (println x))) (comment (fizz-buzz (range 1 101)) (fizz-buzz [1 3 5 10 12 13 15]) ) ;; Alternative solution. ;; I like this better, but it works better for a continuous range of numbers (defn- make-seq "Makes a sequence that returns name at each nth element and nil for others" [name nth] (cycle (concat (repeat (dec nth) nil) [name]))) (def fizzes (make-seq "Fizz" 3)) (def buzzes (make-seq "Buzz" 5)) (def fizzbuzzes (make-seq "FizzBuzz" 15)) (def first-non-nil #(some identity %&)) ;; a lazy seq of FizzBuzzes, Fizzes, Buzzes, and numbers (def fizz-buzz-seq (map first-non-nil fizzbuzzes fizzes buzzes (iterate inc 1))) (defn fizz-buzz-range "Returns FizzBuzz elements from start (inclusive) to end (exclusive), where start defaults to 1." ([end] (fizz-buzz-range 1 end)) ([start end] {:pre [(< start end)]} (->> fizz-buzz-seq (drop (dec start)) (take (- end start))) )) ;; The fizz-buzz-range works well for continuous ranges as the original FizzBuzz problem. ;; This function is to satisfy the spec in the newsletter (ie. pass in integers that could ;; be non-continuous) (defn fizz-buzz-alternative [xs] (doseq [x (map #(first (fizz-buzz-range % (inc %))) xs)] (println x))) (comment (fizz-buzz-range 101) (fizz-buzz-range 100 201) (fizz-buzz-alternative [1 3 5 9 10 12 13 15]) )
 (ns purely-functional-tv-challenges.n394-fizz-buzz (:require [clojure.string :as str])) (defn fizz-buzz-infinite-seq "Infinite fizz buzz sequence where each element is either \"Fizz\", \"Buzz\", \"FizzBuzz\", or a string representing a natural number" [] (let [fizzes (cycle ["" "" "Fizz"]) buzzes (cycle ["" "" "" "" "Buzz"]) fizzes-and-buzzes (map str fizzes buzzes) ints-as-strings (->> (range) (map inc) (map str))] (->> (map vector fizzes-and-buzzes ints-as-strings) ; Seq of pairs of strings ; The line below is where the conditional sneaks in, because we check ; whether the element is a fizz/buzz/fizzbuzz or just a "normal" number. ; If it's a "normal" number then the fizzes-and-buzzes element will be blank. (map #(drop-while str/blank? %) ,,,) ; (map first ,,,)))) (defn fizz-buzz "For each x in xs, print Fizz, Buzz, FizzBuzz, or the number itself, each on a new line. Assume all xs are 1 or greater." [xs] (let [fizz-buzz-seq (fizz-buzz-infinite-seq)] (doseq [x xs] (println (nth fizz-buzz-seq (dec x))))))

### KingCode commented Sep 7, 2020 • edited

 Replacing `doseq` with `map`: ``````(defn fizzbuzz [xs] (let [fizzers (cycle [nil nil "Fizz"]) buzzers (cycle [nil nil nil nil "Buzz"]) fizzbuzzers (cons nil (map #(seq (str % %2)) fizzers buzzers))] (->> xs (map (fn [x] (->> (or (nth fizzbuzzers (max x (- x))) [x]) ((fn [s] (->> s (apply str) (str "\n"))))))) (apply println)))) ``````

### daveschoutens commented Sep 7, 2020

 The instructions say 'loops and conditionals' are off-limits. Can you clarify what counts as a 'loop' for the purposes of this exercise? It seems like `for` might be out, but what about `map`, or other seq functions? (Or indeed, `doseq`)?

### e0d commented Sep 7, 2020

 ``````(defn fizzbuzz [nums] (let [fizz ["Fizz"] buzz ["Buzz"]] (doseq [num nums] (let [out (str (str (get-in fizz [(mod num 3)])) (str (get-in buzz [(mod num 5)])))] (and (seq out) (println out)) (or (seq out) (println num)))))) ``````

### jeremyvdw commented Sep 7, 2020

 ```(defn fizzbuzz [xs] (let [fizz #(zero? (mod % 3)) buzz #(zero? (mod % 5)) fizz-buzz (every-pred fizz buzz)] (reduce (fn [res el] (println (or (and (fizz-buzz el) "FizzBuzz") (and (buzz el) "Buzz") (and (fizz el) "Fizz") el)) res) nil xs)))```

### KingCode commented Sep 7, 2020 • edited

 That’s an interesting question. We could probably say that using `or` or `and` is a direct use of conditionals since they output `if`s. I chose to avoid relying on decision branching in the code I write as per the instructions: so the ones you mention are certainly ok! The instructions say 'loops and conditionals' are off-limits. Can you clarify what counts as a 'loop' for the purposes of this exercise? It seems like `for` might be out, but what about `map`, or other seq functions? (Or indeed, `doseq`)?

### ninjure commented Sep 8, 2020

 ```(defn fizzbuzz [n] (let [m {[false false] n [true false] "fizz" [false true ] "buzz" [true true ] "fizzbuzz"}] (m [(zero? (mod n 3)) (zero? (mod n 5))])))```

### ninjure commented Sep 8, 2020

 ```(defn fizzbuzz [n] (some identity [(get ["fizzbuzz"] (mod n 15)) (get ["buzz"] (mod n 5)) (get ["fizz"] (mod n 3)) n]))```

### daveschoutens commented Sep 8, 2020 • edited

 ```(defn fizzbuzz-val [n] (get {0 (get {0 "FizzBuzz"} (mod n 15) "Fizz")} ;; Does the 'default' argument of `get` count as cheating? :-) (mod n 3) (get {0 "Buzz"} (mod n 5) n))) (defn fizzbuzz [xs] (doseq [x xs] (println (fizzbuzz-val x))))``` Or, if `doseq` is off-limits: ```;; same `fizzbuzz-val as above (defn do-fizzbuzz ([x] (println (fizzbuzz-val x))) ([x & xs] (do-fizzbuzz x) (apply do-fizzbuzz xs))) (defn fizzbuzz [xs] (apply do-fizzbuzz xs))```

### mchampine commented Sep 8, 2020 • edited

 Or, if `doseq` is off-limits: If doseq is too "loopy" then I would think recursion is too! :)

### werand commented Sep 8, 2020 • edited

 ```(defn fizzbuzz [s] (map (fn [n] (get ["fizzbuzz"] (mod n 15) (get ["fizz"] (mod n 3) (get ["buzz"] (mod n 5) n)))) s))```

### ericnormand commented Sep 13, 2020

 The instructions say 'loops and conditionals' are off-limits. Can you clarify what counts as a 'loop' for the purposes of this exercise? It seems like `for` might be out, but what about `map`, or other seq functions? (Or indeed, `doseq`)? Sorry to get to this so late! For me, personally, `doseq` is a loop, but `map` is not. As for `run!`, I'm not sure! I wanted to leave it a little ambiguous to see what people would come up with.

### dosbol commented Oct 6, 2020 • edited

 ``````(defn fizz-buzz [n] (let [rules [[3 "Fizz"] [5 "Buzz"] [15 "FizzBuzz"]]] (reduce (fn [acc [d s]] (if (zero? (mod n d)) s acc)) n rules))) ``````