Browse code
feat: clojure max-subarray
Ed Langley authored on 29/10/2020 23:39:40
Showing 1 changed files
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))))))) |