git.fiddlerwoaroof.com
Browse code

feat: clojure max-subarray

Ed Langley authored on 29/10/2020 23:39:40
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,50 @@
1
+(ns max-subarray
2
+  (:require [clojure.test :refer [deftest is]]))
3
+
4
+(defn propagating
5
+  "Transducer that emits the current maximum value, according to cmp"
6
+  [init cmp]
7
+  (fn [rf]
8
+    (let [cur-max (volatile! init)]
9
+      (completing
10
+       (fn [acc nxt]
11
+         (vswap! cur-max cmp nxt)
12
+         (rf acc @cur-max))))))
13
+
14
+(defn max-sequence [xs]
15
+  (-> (into [0]
16
+            (comp (propagating 0 (comp #(max 0 %) +)) ;; Maintain the running sum, as long as it's non-zero
17
+                  (propagating 0 max))                ;; Emit the current maximum running sum
18
+            xs)
19
+      peek)) ;; Get the last maximum running sum (peek on vector makes this fast)
20
+
21
+(deftest simple
22
+  (is (= (max-sequence  [-2, 1, -3, 4, -1, 2, 1, -5, 4]) 6))
23
+  (is (= (max-sequence  []) 0))
24
+  (is (= (max-sequence  [1 2 3 4]) 10))
25
+  (is (= (max-sequence  [-1 -2 -3 -4]) 0))
26
+
27
+  )
28
+
29
+(defn collect-runs [eq]
30
+  (let [sentinel (Object.)]
31
+    (fn [rf]
32
+      (let [c-v (atom sentinel)
33
+            current (atom [])]
34
+        (fn
35
+          ([] (rf))
36
+          ([acc] (rf (rf acc @current)))
37
+          ([acc nxt]
38
+           (when (= @c-v sentinel)
39
+             (reset! c-v nxt))
40
+           (let [result (if (eq @c-v nxt)
41
+                          (do (swap! current conj nxt)
42
+                              acc)
43
+                          (let [r (rf acc @current)]
44
+                            (reset! current [nxt])
45
+                            r))]
46
+             (reset! c-v nxt)
47
+             result)))))))
48
+
49
+(defn series-sum [n]
50
+  (format "%.2f" (double (apply + (map #(/ 1.0 (doto % prn)) (take n (iterate #(+ % 3.0) 1.0)))))))