Skip to content

Instantly share code, notes, and snippets.

@stuarthalloway
Created August 12, 2017 22:41
Show Gist options
  • Select an option

  • Save stuarthalloway/01a2b7233b1285a8b43dfc206ba0036e to your computer and use it in GitHub Desktop.

Select an option

Save stuarthalloway/01a2b7233b1285a8b43dfc206ba0036e to your computer and use it in GitHub Desktop.

Revisions

  1. stuarthalloway created this gist Aug 12, 2017.
    44 changes: 44 additions & 0 deletions FizzBuzz.clj
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    ;; try this form-by-form at a REPL
    (require '[clojure.spec.alpha :as s])

    ;; create an inline DSL to describe the FizzBuzz world
    (defmacro divides-by
    [nm n]
    `(s/def ~nm (s/and pos-int? #(zero? (mod % ~n)))))

    ;; specify FizzBuzz
    (divides-by ::fizz 3)
    (divides-by ::buzz 5)
    (divides-by ::fizzbuzz 15)

    ;; try it out
    (s/conform ::fizz 4)
    (s/exercise ::fizz)

    ;; specify all of FizzBuzz so it can generate
    (s/def ::fizzbuzznum
    (s/and (s/or :name (s/and (s/or :FizzBuzz ::fizzbuzz :Buzz ::buzz :Fizz ::fizz)
    (s/conformer (comp name first)))
    :num pos-int?)
    (s/conformer second)))

    ;; take it for a stroll...
    (s/exercise ::fizzbuzznum 25)

    ;; oops, almost forgot to solve the problem...
    (def fizzbuzz-transducer (map (partial s/conform ::fizzbuzznum)))

    ;; ...lazily generate FizzBuzz for all the integers
    (set! *print-length* 100)
    (eduction fizzbuzz-transducer (range 1 101))

    ;; load a unit test library
    (require '[clojure.edn :as edn])

    ;; comprehensive test suite
    (assert (= (eduction fizzbuzz-transducer (range 1 101))
    (-> "https://gist.github.com/stuarthalloway/ad1041d65b84626e5b8009e51ad69260/raw" slurp edn/read-string)))

    ;; Since FizzBuzz is used for interviews, here is an interview question:
    ;; Given the implementation above, why is it desirable that this number be small?
    (Math/pow (/ 14.0 15) 100)