Skip to content

Instantly share code, notes, and snippets.

@jimpil
Last active July 19, 2023 20:22
Show Gist options
  • Save jimpil/ed7f6cf9729955c1d6c99463defb9c3d to your computer and use it in GitHub Desktop.
Save jimpil/ed7f6cf9729955c1d6c99463defb9c3d to your computer and use it in GitHub Desktop.
Double-Cola (CodeWars) Clojure solutions
(ns double-cola.core)
;Sheldon, Leonard, Penny, Rajesh and Howard are in the queue
;for a "Double Cola" drink vending machine; there are no other
;people in the queue. The first one in the queue (Sheldon) buys
;a can, drinks it and doubles! The resulting two Sheldons go to
;the end of the queue. Then the next in the queue (Leonard) buys
;a can, drinks it and gets to the end of the queue as two Leonards,
;and so on.
(def theq ["Sheldon" "Leonard" "Penny" "Rajesh" "Howard"])
(defn- expand [q i] (mapcat (partial repeat (Math/pow 2 (double i))) q))
(defn who-drinks-lazy
[q nth-cola]
{:pre [(seq q)
(pos-int? nth-cola)]}
(-> (partial expand q)
(mapcat (range))
(nth (dec nth-cola))))
(comment
(who-drinks-lazy theq 1) ;; => "Sheldon"
(who-drinks-lazy theq 52) ;; => "Penny"
(who-drinks-lazy theq 10010) ;; => "Howard"
(who-drinks-lazy theq 7230702951) ;; => ArithmeticException (integer-overflow) - wtf?
)
(defn who-drinks-optimised
[q nth-cola]
{:pre [(seq q)
(pos-int? nth-cola)]}
(let [q-count (count q)]
(loop [round 1
total q-count]
(let [repetitions (long (Math/pow 2 (double (dec round))))]
(if (<= nth-cola total)
(let [round-total (* q-count repetitions)
cutoff (- total nth-cola)
round-index (- round-total cutoff 1)]
(->> (range 0 (inc round-total) repetitions) ;; 6 elements
(partition 2 1) ;; 5 boundary groups (i.e. [start end])
(keep-indexed
(fn [i [start end]]
(when (< (dec start) round-index end)
(nth q i))))
first))
(recur (inc round)
(+ total (* q-count (* 2 repetitions)))))))))
(comment
(who-drinks-optimised theq 1) ;; => "Sheldon"
(who-drinks-optimised theq 52) ;; => "Penny"
(who-drinks-optimised theq 10010) ;; => "Howard"
(time (who-drinks-optimised theq 7230702951)) ;; => "Leonard"
)
(defn who-drinks-clever
[q nth-cola]
{:pre [(seq q)
(pos-int? nth-cola)]}
(let [qcount (count q)
qcount-1 (dec qcount)]
(loop [n nth-cola]
(if (> n qcount)
(recur (-> (- n qcount-1)
(/ 2)
long))
(nth q (dec n))))))
(comment
(who-drinks-clever theq 1) ;; => "Sheldon"
(who-drinks-clever theq 52) ;; => "Penny"
(who-drinks-clever theq 10010) ;; => "Howard"
(time (who-drinks-clever theq 7230702951)) ;; => "Leonard"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment