Last active
September 21, 2016 10:40
-
-
Save markwoodhall/7b76adc715ac3f21e9bfe747678aee58 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(def contents [123 123 123 456 567 890 444 444 555]) | |
(def track-out [123 890 444]) | |
;; Expected output (123 123 456 567 444 555) | |
(flatten (remove (into #{} track-out) (map #(if (= (count %) 1) (first %) (rest %)) (partition-by identity contents)))) |
Nice! Thanks!
(require '[clojure.core.async :as async])
(defn f [parallelism to-remove input]
(let [in (async/chan parallelism)
out1 (async/chan parallelism)
dist (async/pub in #(mod (hash (second %)) parallelism))]
(dotimes [i parallelism]
(let [in (async/chan)]
(async/sub dist i in)
(async/go-loop [seen #{}]
(when-let [[output item] (async/<! in)]
(if (contains? seen item)
(async/>! output item)
(when (not (contains? to-remove item))
(async/>! output item)))
(async/close! output)
(recur (conj seen item))))))
(async/go
(doseq [item input
:let [oc (async/chan 1)]]
(async/>! in [oc item])
(async/>! out1 oc))
(async/close! in)
(async/close! out1))
(async/<!!
(async/go-loop [accum []]
(if-let [oc (async/<! out1)]
(if-let [item (async/<! oc)]
(recur (conj accum item))
(recur accum))
accum)))))
;;user=> (f 18 #{123 890 444} [123 123 123 456 567 890 444 444 555])
[123 123 456 567 444 555]
;;user=>
That looks totally nuts! :)
How about a stateful transducer:
(defn filter-first
[f]
(fn [rf]
(let [f-atom (atom f)]
(fn
([]
(reset! f-atom f)
(rf))
([acc x]
(let [remaining-f @f-atom]
(if (and (remaining-f x)
(compare-and-set! f-atom remaining-f (disj remaining-f x)))
acc
(rf acc x))))
([acc]
(rf acc))))))
(transduce (filter-first (set track-out)) conj contents) => [123 123 456 567 444 555]
(into '() (filter-first (set track-out)) contents) => (555 444 567 456 123 123)
(async/pipeline 18 to (filter-first (set track-out)) from)
With this you can use the logic over all manner of things!
Another one, for reference.
(defn mask-remove-one
[from to]
(persistent!
(loop [bads (set from)
accu (transient [])
goods to]
(if (nil? goods)
accu
(let [val (first goods)]
(cond
(contains? bads val) (recur (disj bads val)
accu
(next goods))
:else (recur bads (conj! accu val) (next goods))))))))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Recursion with some lazy seqs and a sprinkling of sets:
Have fun!