Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@adityaathalye
Created September 2, 2019 09:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adityaathalye/cd3f275086285f15e384ad3707d9cc16 to your computer and use it in GitHub Desktop.
Save adityaathalye/cd3f275086285f15e384ad3707d9cc16 to your computer and use it in GitHub Desktop.
Too many crackle-poppers
(ns too.many.crackle-poppers)
;; ABOUT:
;;
;; Solutions to CracklePop, incidentally written in Clojure.
;;
;; READING GUIDE:
;;
;; - See the 'check-all-crackle-poppers' function at the bottom, for usage examples.
;; - All the solutions use Clojure's standard library functions.
;; - Lookup unfamiliar functions at https://clojuredocs.org/quickref
;; - Let's call the solutions a bunch of "Crackle Poppers", because why not?
;;
;; USAGE GUIDE:
;;
;; If you are a Clojure user, switch to this ns, compile, and start REPL-ing
;; up from the forms at the bottom.
;;
;; If you aren't a Clojure user, do the following to try out the solutions:
;;
;; - Visit https://repl.it/languages/clojure to access a Clojure REPL session.
;;
;; - Copy-paste the entire contents of this file into the "main.clj" area.
;;
;; - Hit "Run". You should see some output in the accompanying "REPL" area.
;; The output corresponds to all the top-level constants and functions
;; that were defined as a consequence of the "Run".
;;
;; - Type `(check-all-crackle-poppers)` in the REPL (including the parentheses)
;; and hit Enter to evaluate that function---it's a zero-argument function.
;; This evaluation should return 'true', which the REPL will print.
;;
;; - Likewise; try evaluating individual calls to the various crackle poppers.
;; For example, evaluate: (crackle-pop canonical-popper range-of-popees)
;; Here `crackle-pop` is a function that gets passed two arguments.
;;
;; - To see what `range-of-popees` is, evaluate it as-is in the REPL
;; (type without parentheses, and hit Enter). Similarly, try evaluating
;; `crackle-pop`, or `canonical-popper` expressions and see what you get.
;;
;; CANONICAL IMPLEMENTATION
;; - The crackle pop we all know and love.
;;
(def div?
"True when the remainder of n1/n2 is zero. e.g. (div? 4 2) => true"
(comp zero? rem))
(defn canonical-popper
"First trap all prime factors. Then trap each unique factor one by one.
Default to the given number. Order of conditional checks matters."
[n]
(cond
(div? n 15) "CracklePop"
(div? n 3) "Crackle"
(div? n 5) "Pop"
:else n))
;;
;; HERETICAL IMPLEMENTATIONS
;; - Some oddball and not-so-oddball Crackle Poppers, using features of Clojure,
;; and of functional programming.
;;
(defn crackles?
"Truthy when it crackles, Falsey (nil) otherwise.
Clojure branching/predicate logic accepts Truthy/Falsey."
[n]
(when (div? n 3) "Crackle"))
(defn pops?
"Truthy only when it pops."
[n]
(when (div? n 5) "Pop"))
(defn cracklepops?
"Truthy only when it crackles _and_ pops."
[n]
(when (div? n 15) "CracklePop"))
(defn or-popper
"Just like conditional matching, but exploit short-circuit behaviour of 'or'.
Order of conditional checks matters."
[n]
(or (cracklepops? n)
(crackles? n)
(pops? n)
n))
(defn juxt-popper
"Once someone discovers `juxt`, it _must_ be used _everywhere_. EVERYWHERE.
MMWAAAAHAHAHAHAHAHAHAAHHAAAAA. Order of conditional checks matters.
((juxt f g h) 42) -> [(f 42) (g 42) (h 42)]
cf. https://clojuredocs.org/clojure.core/juxt"
[n]
(some identity ((juxt cracklepops? crackles? pops? identity)
n)))
(defn lookup-popper
"Encode crackle pop as a lookup table based on remainders of 15.
Order of match ceases to matter."
[n]
(let [crackle-pop-lookup-table {0 "CracklePop"
3 "Crackle"
6 "Crackle"
9 "Crackle"
12 "Crackle"
5 "Pop"
10 "Pop"}]
(get crackle-pop-lookup-table
(rem n 15)
;; default to the given 'n', when not looked-up
n)))
(def cyclical-popper
"Encode crackle pop as a repeating sequence... it is cyclic in modulo 3, 5, and 15.
The sequence is ordered by definition."
(let [n identity
c (constantly "Crackle")
p (constantly "Pop")
cp (constantly "CracklePop")]
(cycle [n n c
n p c
n n c
p n c
n n cp])))
;;
;; USAGE EXAMPLES
;;
(def range-of-popees (range 1 101)) ; a sea of popees would be too big
(def crackle-pop map) ; now, what `map` can do crackle-pop can too
(defn check-all-crackle-poppers
"A quick and dirty test. Canonical or Heretical, do all the Poppers
ultimately agree with each other?"
[]
(= (crackle-pop canonical-popper
range-of-popees)
(crackle-pop or-popper
range-of-popees)
(crackle-pop juxt-popper
range-of-popees)
(crackle-pop lookup-popper
range-of-popees)
(crackle-pop (fn [f n] (f n))
cyclical-popper
range-of-popees)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment