Skip to content

Instantly share code, notes, and snippets.

@nha
Last active October 14, 2016 13:22
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 nha/f1474c905b38a7bf5466 to your computer and use it in GitHub Desktop.
Save nha/f1474c905b38a7bf5466 to your computer and use it in GitHub Desktop.
merge-date
(ns merge-date.core)
(def sorted-time-range (sort-by first '([1 3] [3 4] [47 52] [12 44])))
(defn merge-date-tuple [[b0 e0] [b1 e1]]
(if (>= e0 b1)
[[b0 (max e0 e1)]]
[[b0 e0] [b1 e1]]))
(defn merge-date
([coll] (merge-date (rest coll)
[(first coll)]))
([coll res] (if (empty? coll)
res
(recur (rest coll)
(concat (drop-last res)
(merge-date-tuple (last res)
(first coll)))))))
(println "===> result " (merge-date sorted-time-range))
;; heavy use of destructuring
(defn merge-date [coll]
(let [s (sort-by first coll)
{a :a p :p} (reduce (fn [{[p1 p2 :as p] :p a :a} [x1 x2 :as el]]
(if (>= p2 x1)
{:a a :p [p1 x2]}
{:a (conj a p) :p el}))
{:a [] :p (first s)} (rest s))]
(concat a p)))
(merge-date '([1 3] [3 4] [47 52] [12 44]))
;; small gist to compare a merge date algorithm in Clojure with another language (code not here)
(ns merge-date.core)
;; fake step 1
;; define a variable for the unsorted array
(def unsorted-time-range '([1 3] [3 4] [47 52] [12 44]))
;; step 2 : sort the array and store it in sorted-time-range
(def sorted-time-range (sort-by first unsorted-time-range))
(println "sorted " sorted-time-range)
;; step 3
; helper function to merge two time slots
(defn merge-date-tuple
[[b0 e0] [b1 e1]] ; function arguments (destructured)
{:pre [(<= b0 e0) ; (optionnal) preconditions
(<= b1 e1)
(<= b0 b1)]}
(if (>= e0 b1) ; if(end-date-current >= begin-date-next
[[b0 (max e0 e1)]] ; true => merge
[[b0 e0] [b1 e1]])) ; false => return arguments
; merge an array of time slots
(defn merge-date
;; called with only one argument : the collection (array of time slots)
;; initialise the res variable with the first element from the sorted collection
([coll] (merge-date (rest coll) [(first coll)]))
;; two arguments : the collection to be merged, the result already merged
([coll res] (if (empty? coll)
res ; done, return result
; define variables
(let [current (last res) ; current : first element of res
next (first coll) ; next : first element of coll
merged (merge-date-tuple current next)] ; merge current and next using helper function
;; call the function again (recursive) with two arguments :
;; - the rest of the collection to be merged
;; - the partial result constructed so far (by concatenating the previous result with the merged tuple)
(println "\n")
(println "to be merged", (rest coll))
(println "already merged", (concat (drop-last res) merged))
(recur (rest coll) (concat (drop-last res) merged))))))
(println "===> result " (merge-date sorted-time-range))
;; prints the following :
; sorted ([1 3] [3 4] [12 44] [47 52])
; to be merged ([12 44] [47 52])
; already merged ([1 4])
; to be merged ([47 52])
; merged ([1 4] [12 44])
; to be merged ()
; already merged ([1 4] [12 44] [47 52])
===> result ([1 4] [12 44] [47 52])
(defn md [coll]
(let [[f & r] (sort-by first coll)]
(if f
(reduce (fn [a e]
(let [[b1 e1] e
[b0 e0] (last a)
c (count a)]
(if (<= b1 e0)
(assoc a (dec c) [b0 e1])
(assoc a c e)))) [f] r)
[])))
;;commented
;; define a function "md" that takes a collection in parameter
(defn md [coll]
;; sort the collection by the first item (begin date)
;; and destructure it into the first element and the rest
(let [[f & r] (sort-by first coll)]
;; if there is a first element (ie. if the collection is not empty)
(if f
;; then loop over it, one element at a time
(reduce (fn [a e]
;; a contains the result that is being built every iteration (a=accumulator)
;; e contains the new element that we want to add
(let [;; destructure the last element from the result into a beginning date b0 and an end date e0
[b0 e0] (last a)
;; destructure the new element into the beginning b1 and the end e1
[b1 e1] e
;; get the number of elements that we have already in the result vector. Accessing a at the index c - 1 will point to the last element of the vector
c (count a)]
(if (<= b1 e0) ;; if we want to merge the dates
;; then replace the last element of a (at index c - 1) with a couple [b0 e1]
(assoc a (dec c) [b0 e1])
;; if don't want to merge the date, then add the new element at the end of the vector (index c)
(assoc a c e)))) [f] r)
;; if it was empty then return an empty array
[])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment