This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-02-01
Channels
- # aleph (6)
- # announcements (37)
- # aws (1)
- # beginners (67)
- # calva (9)
- # clerk (5)
- # clj-kondo (3)
- # clojure (19)
- # clojure-europe (40)
- # clojure-nl (1)
- # clojure-norway (36)
- # clojure-uk (5)
- # clojuredesign-podcast (7)
- # clojurescript (28)
- # datomic (9)
- # emacs (8)
- # figwheel-main (4)
- # fulcro (6)
- # hyperfiddle (19)
- # integrant (4)
- # java (9)
- # lsp (131)
- # malli (9)
- # missionary (85)
- # off-topic (13)
- # pathom (3)
- # polylith (11)
- # releases (1)
- # sci (4)
- # shadow-cljs (7)
- # specter (2)
- # vscode (1)
- # xtdb (2)
I've been noodling around with "Elements of Programming Interviews" (highly recommended if you enjoy algorithm puzzles) and I'm wondering if there's an idiomatic Clojure/functional way to implement an imperative-style "sliding-window" algorithm? Example: find the smallest subarray that contains all members of a set, e.g. given array ["a", "b", "c", "b", "a", "d", "c", "a", "e", "a", "a", "b", "e"]
and set {"b", "c", "e"}
, the smallest subarray containing b, c, and e is from indexes 3 - 8.
One way to do this is to have two pointers starting at index 0, run the first pointer down the array until it's encountered at least one of each of the set members, then run the second pointer behind it until the subarray they span no longer contains all set members, then repeat until the first pointer reaches the end, keeping track of the shortest distance encountered between the two pointers.
I can't think of a way to do this in Clojure that doesn't either do essentially the same thing with a while loop or something, or else generates a list of all possible subarrays and then filters them, which is not nearly as efficient.
If generating all possible subarrays is lazy then it may be surprisingly efficient. unlikely to beat the loop over indices, but not as bad as you might think.
In an imperative language you'll use a for or while loop, in a functional one you'll use some kind recursion
Excellent points -- I work on very-much-not-functional enterprise Java for my day job so maybe I'm overthinking the functional part. I'd thought about a recursive solution but it just seemed like fundamentally the same thing as moving pointers around, but maybe that's ok.
I don’t know if this is a good idea or not, but it might be an interesting one:
• have a recursive fn or loop that takes a seq and an accumulator
• take-while
on the first seq until it contains all the set members
• Take the seq you found and drop-while
all the set members are still in it. I might do this in a separate fn rather than a tight loop.
• Add that span to the accumulator and repeat until the seq is empty
You’ll want to use split-with
rather than take/drop-while
so you have access to the rest of the seq after taking/dropping the elements you want, but it’ll be take/drop-while
-like in spirit. Performance probably won’t be as good as if you used a loop because of the seq overhead, but maybe it’ll get close if you use transducers?
Using partition
with a step-size of 1
is the standard way to get a "sliding window" over a collection in clojure, so something like this would be a fairly typical approach:
(defn shortest-subseq [test-set coll]
(let [matching (fn [ss] (when (every? (fn [p] (some #(= p %) ss)) test-set) ss))]
(loop [part-size (count test-set)]
(when (<= part-size (count coll))
(or (some matching (partition part-size 1 coll))
(recur (inc part-size)))))))
(shortest-subseq #{"b" "c" "e"} input)
;; => ("b" "a" "d" "c" "a" "e")
Would any commonly used library break, if I define a print-method
for (byte-array)
s, printing them as hex strings?
(defmethod print-method (class (byte-array 0)) ...)
I want to be able to roundtrip some byte-arrays through AWS SSM params as EDN, without custom handling for byte-array values.
something like this:
;;; Experiment for automatically returning SSM secret param values as a byte-array
(def ^java.util.HexFormat hex-formatter (java.util.HexFormat/of))
(defn parse-hex ^bytes [^String hex-str] (.parseHex hex-formatter hex-str))
(defn format-hex ^String [^bytes a-byte-array] (.formatHex hex-formatter a-byte-array))
(defmethod print-method (class (byte-array 0))
[a-byte-array ^java.io.Writer writer]
(doto writer
(->> (print-method (tagged-literal 'hex (format-hex a-byte-array))))))
(defn edn-encode [x]
(binding [*print-level* 32 *print-length* nil *print-dup* false *print-namespace-maps* false]
(pr-str x)))
(defn edn-decode [edn-str]
(edn/read-string {:readers {'hex parse-hex}} edn-str))
(comment
(-> [1 2 3 10 11 12] byte-array edn-encode edn-decode)
)
btw, I just heard about java.util.HexFormat
a few months ago, which was introduced in Java 17.
Here is a quick intro article about it:
https://www.baeldung.com/java-hexformat