Skip to content

Instantly share code, notes, and snippets.

@caioaao
Created April 22, 2019 12:34
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 caioaao/6c0162c8bb71c81d136c5770aacc67cb to your computer and use it in GitHub Desktop.
Save caioaao/6c0162c8bb71c81d136c5770aacc67cb to your computer and use it in GitHub Desktop.
Solution for range consolidation challenge from purelyfunctional.tv newsletter
(ns caioaao.purely-functional.solutions.range-consolidation)
(defn ranges->events [vs]
(mapcat (fn [[a b]] [[:open a] [:close b]]) vs))
(def type->priority
{:open 1
:close 2})
;; since range includes both ends, `open` events have priority over `close`
;; ones.
(defn sorted-events [evts]
(sort-by (juxt second (comp type->priority first)) evts))
(defn events->ranges [evts]
(let [evts (sorted-events evts)]
(assert (= :open (ffirst evts))
"First event should always be opening a range")
(loop [result []
range-start (-> evts first second)
ranges-open 1
[[evt-type evt-point] & evts] (rest evts)]
(cond
(not evt-type)
(do (assert (zero? ranges-open) "Open-ended ranges are not allowed")
result)
(= :open evt-type)
(recur result
(if (zero? ranges-open) evt-point range-start)
(inc ranges-open)
evts)
(and (= :close evt-type)
(= 1 ranges-open))
(recur (conj result [range-start evt-point])
nil
0
evts)
:default
(recur result range-start (dec ranges-open) evts)))))
(defn consolidate [vs]
(-> vs
ranges->events
events->ranges))
(comment
(consolidate [[1 4] [3 5]])
(consolidate [[1 4] [3 5] [10.2 15]])
(consolidate [[1 4] [4 5]])
(consolidate [[1 4] [5 5]]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment