diff --git a/src/combinatorics/stirling_bell/stirling_bell.clj b/src/combinatorics/stirling_bell/stirling_bell.clj index c36c02c..5ca7d4a 100644 --- a/src/combinatorics/stirling_bell/stirling_bell.clj +++ b/src/combinatorics/stirling_bell/stirling_bell.clj @@ -8,25 +8,27 @@ (if (str/blank? t) [] (vec (str/split t #"\s+"))))) (defn parse-token [t] t) (defn as-long [t] (Long/parseLong t)) -(defn stirling-table [n k kind] - (loop [i 1 T (assoc (vec (repeat (inc n) (vec (repeat (inc k) 0)))) 0 (assoc (vec (repeat (inc k) 0)) 0 1))] - (if (> i n) T - (recur (inc i) (loop [j 1 T T] - (if (or (> j k) (> j i)) T - (recur (inc j) (assoc-in T [i j] - (if (= kind 2) - (+ (* j (nth (nth T (dec i)) j)) (nth (nth T (dec i)) (dec j))) - (+ (* (- (dec i)) (nth (nth T (dec i)) j)) (nth (nth T (dec i)) (dec j)))))))))))) +(defn stirling-row [n k kind] + (loop [i 0 prev (assoc (vec (repeat (inc k) 0)) 0 1)] + (if (>= i n) prev + (let [i1 (inc i) + cur (loop [j 1 cur (vec (repeat (inc k) 0))] + (if (or (> j k) (> j i1)) cur + (recur (inc j) (assoc cur j + (if (= kind 2) + (+ (* j (nth prev j)) (nth prev (dec j))) + (+ (* (- i) (nth prev j)) (nth prev (dec j))))))))] + (recur i1 cur))))) (defn -main [] (let [toks (tokenize (slurp *in*))] (when (seq toks) (cond (= "S2" (nth toks 0)) (let [n (as-long (nth toks 1)) k (as-long (nth toks 2))] - (println (nth (nth (stirling-table n k 2) n) k))) + (println (nth (stirling-row n k 2) k))) (= "S1" (nth toks 0)) (let [n (as-long (nth toks 1)) k (as-long (nth toks 2))] - (println (nth (nth (stirling-table n k 1) n) k))) + (println (nth (stirling-row n k 1) k))) :else (let [n (as-long (nth toks 1))] - (println (reduce + (nth (stirling-table n n 2) n)))))))) + (println (reduce + (stirling-row n n 2)))))))) (-main) diff --git a/src/compiler/attribute_grammar.clj b/src/compiler/attribute_grammar.clj index f20f2d6..13ea925 100644 --- a/src/compiler/attribute_grammar.clj +++ b/src/compiler/attribute_grammar.clj @@ -10,10 +10,10 @@ (defn tokenize [s] (str/split (str/trim s) #"\s+")) (defn parse-token [t] (Long/parseLong t)) -(defn synth [node] - (if (nil? (:l node)) - (:bit node) - (+ (* (synth (:l node)) 2) (:bit node)))) +(defn synth-bits [bs] + (loop [i 0 acc 0] + (if (= i (count bs)) acc + (recur (inc i) (+ (* acc 2) (if (= (.charAt bs i) \1) 1 0)))))) (defn -main [] (let [toks (tokenize (slurp *in*))] @@ -22,11 +22,7 @@ (print (str sb)) (let [sg (nth toks pos) bs (nth toks (inc pos)) - root (loop [i 0 r nil] - (if (= i (count bs)) - r - (recur (inc i) {:l r :bit (if (= (.charAt bs i) \1) 1 0)}))) - v (synth root)] + v (synth-bits bs)] (.append sb (str "ATTR " (if (= sg "-") (- v) v) "\n")) (recur (+ pos 2) (dec tcases) sb)))))) diff --git a/src/data_structure/bst_lca/binary_search_tree_lowest_common_ancestor.clj b/src/data_structure/bst_lca/binary_search_tree_lowest_common_ancestor.clj index 0b10c6b..0615e0e 100644 --- a/src/data_structure/bst_lca/binary_search_tree_lowest_common_ancestor.clj +++ b/src/data_structure/bst_lca/binary_search_tree_lowest_common_ancestor.clj @@ -55,13 +55,24 @@ (println msg))) (defn bst-insert - "Insert v into the search tree, sending duplicates right." + "Insert v into the search tree, sending duplicates right. + Iterative: descends with an explicit path, then rebuilds bottom-up." [tree v] (if (nil? tree) {:val v :left nil :right nil} - (if (< v (:val tree)) - (assoc tree :left (bst-insert (:left tree) v)) - (assoc tree :right (bst-insert (:right tree) v))))) + (let [path (loop [cur tree path []] + (let [side (if (< v (:val cur)) :left :right)] + (if (nil? (side cur)) + (conj path [cur side]) + (recur (side cur) (conj path [cur side]))))) + leaf {:val v :left nil :right nil} + n (count path) + [bot bside] (nth path (dec n))] + (loop [node (assoc bot bside leaf) idx (- n 2)] + (if (neg? idx) + node + (let [[p pside] (nth path idx)] + (recur (assoc p pside node) (dec idx)))))))) (defn lowest-common-ancestor "Walk down from root toward the split point of lo and hi." diff --git a/src/data_structure/red_black_tree/solution.clj b/src/data_structure/red_black_tree/solution.clj index 1a92565..2d09c74 100644 --- a/src/data_structure/red_black_tree/solution.clj +++ b/src/data_structure/red_black_tree/solution.clj @@ -135,22 +135,40 @@ (< k ck) (recur (:l cur)) :else (recur (:r cur))))))) -(defn insert-node - "Insert key k into subtree h." - [h k] - (if (nil? h) - {:k k :c :red :l nil :r nil} - (let [ck (:k h) - h (cond - (< k ck) (assoc h :l (insert-node (:l h) k)) - (> k ck) (assoc h :r (insert-node (:r h) k)) - :else h)] - (balance h)))) - (defn rb-insert - "Insert key k into root and color root black." + "Insert key k into root and color root black. + Iterative: descends with an explicit path, attaches a red leaf, + then rebuilds bottom-up applying the same fixup (balance) at + each level, including on the duplicate path." [root k] - (assoc (insert-node root k) :c :black)) + (if (nil? root) + {:k k :c :black :l nil :r nil} + (let [desc (loop [cur root path []] + (let [path (conj path cur) + ck (:k cur)] + (cond + (= k ck) {:path path :found true} + (< k ck) (if (nil? (:l cur)) + {:path path :found false} + (recur (:l cur) path)) + :else (if (nil? (:r cur)) + {:path path :found false} + (recur (:r cur) path))))) + path (:path desc) + found (:found desc) + n (count path) + bot (nth path (dec n)) + node (balance (if found + bot + (assoc bot (if (< k (:k bot)) :l :r) + {:k k :c :red :l nil :r nil})))] + (assoc (loop [node node idx (- n 2)] + (if (neg? idx) + node + (let [p (nth path idx)] + (recur (balance (assoc p (if (< k (:k p)) :l :r) node)) + (dec idx))))) + :c :black)))) (defn min-node "Smallest node in non-empty subtree h." diff --git a/src/math/approximation/mult_weights/mult_weights.clj b/src/math/approximation/mult_weights/mult_weights.clj index 447fc5c..752aa5c 100644 --- a/src/math/approximation/mult_weights/mult_weights.clj +++ b/src/math/approximation/mult_weights/mult_weights.clj @@ -16,10 +16,10 @@ T (long (Double/parseDouble (nth toks 1))) eta (parse-token (nth toks 2)) vals (mapv parse-token (drop 3 toks)) - g (vec (for [tt (range T)] (vec (for [i (range n)] (nth vals (+ (* tt n) i)))))) w (loop [tt 0 w (vec (repeat n 1.0))] (if (>= tt T) w - (recur (inc tt) (mapv (fn [i] (* (nth w i) (+ 1 (* eta (nth (nth g tt) i))))) (range n))))) + (let [base (* tt n)] + (recur (inc tt) (mapv (fn [i] (* (nth w i) (+ 1 (* eta (nth vals (+ base i)))))) (range n)))))) s (reduce + w)] (println (str/join " " (map (fn [v] (fmt (/ v s))) w))))))) (-main) diff --git a/src/sort/three_way_quicksort/solution.clj b/src/sort/three_way_quicksort/solution.clj index b485347..21a8e70 100644 --- a/src/sort/three_way_quicksort/solution.clj +++ b/src/sort/three_way_quicksort/solution.clj @@ -28,12 +28,39 @@ (defn read-int [tok] (parse-token tok)) (defn three-way-qsort [a] - (if (<= (count a) 1) a - (let [pivot (nth a (quot (count a) 2)) - less (filterv #(< % pivot) a) - equal (filterv #(= % pivot) a) - greater (filterv #(> % pivot) a)] - (vec (concat (three-way-qsort less) equal (three-way-qsort greater)))))) + (let [n (count a)] + (if (<= n 1) a + (let [^longs arr (long-array a) + stack (java.util.ArrayDeque.)] + (.push stack (long-array [0 (dec n)])) + (while (not (.isEmpty stack)) + (let [^longs rng (.pop stack) + lo (aget rng 0) hi (aget rng 1)] + (when (< lo hi) + (let [pivot (aget arr (+ lo (quot (inc (- hi lo)) 2)))] + (loop [lt lo i lo gt hi] + (if (> i gt) + (do + ;; Push the larger side first so the smaller side is + ;; processed first; stack depth stays O(log n). + (let [nl (- lt lo) nr (- hi gt)] + (if (< nl nr) + (do (.push stack (long-array [lo (dec lt)])) + (.push stack (long-array [(inc gt) hi]))) + (do (.push stack (long-array [(inc gt) hi])) + (.push stack (long-array [lo (dec lt)])))))) + (let [x (aget arr i)] + (cond + (< x pivot) + (let [t (aget arr lt)] + (aset arr lt x) (aset arr i t) + (recur (inc lt) (inc i) gt)) + (> x pivot) + (let [t (aget arr gt)] + (aset arr gt x) (aset arr i t) + (recur lt i (dec gt))) + :else (recur lt (inc i) gt))))))))) + (vec arr))))) (defn -main [] (let [input (slurp *in*) toks (tokenize input) n (if (seq toks) (read-int (first toks)) 0) diff --git a/src/sort/three_way_string_quicksort/solution.clj b/src/sort/three_way_string_quicksort/solution.clj index 0474eb6..c66f5aa 100644 --- a/src/sort/three_way_string_quicksort/solution.clj +++ b/src/sort/three_way_string_quicksort/solution.clj @@ -27,16 +27,37 @@ (recur (rest d) nxt)))))))))))) (defn read-int [tok] (parse-token tok)) -(defn char-at [s d] (if (< d (count s)) (int (.charAt s d)) -1)) +(defn char-at [^String s ^long d] (if (< d (count s)) (int (.charAt s d)) -1)) (defn three-way-str-qsort [a d] - (if (<= (count a) 1) a - (let [pivot-c (char-at (first a) d) - less (filterv #(< (char-at % d) pivot-c) a) - equal (filterv #(= (char-at % d) pivot-c) a) - greater (filterv #(> (char-at % d) pivot-c) a) - eq-sorted (if (= pivot-c -1) equal - (three-way-str-qsort equal (inc d)))] - (vec (concat (three-way-str-qsort less d) eq-sorted (three-way-str-qsort greater d)))))) + (let [n (count a)] + (if (<= n 1) a + (let [^objects arr (object-array a) + stack (java.util.ArrayDeque.)] + (.push stack (long-array [0 (dec n) d])) + (while (not (.isEmpty stack)) + (let [^longs rng (.pop stack) + lo (aget rng 0) hi (aget rng 1) dd (aget rng 2)] + (when (< lo hi) + (let [pivot-c (char-at (aget arr lo) dd)] + (loop [lt lo i lo gt hi] + (if (> i gt) + (do + (.push stack (long-array [lo (dec lt) dd])) + (.push stack (long-array [(inc gt) hi dd])) + (when (not= pivot-c -1) + (.push stack (long-array [lt gt (inc dd)])))) + (let [c (char-at (aget arr i) dd)] + (cond + (< c pivot-c) + (let [t (aget arr lt)] + (aset arr lt (aget arr i)) (aset arr i t) + (recur (inc lt) (inc i) gt)) + (> c pivot-c) + (let [t (aget arr gt)] + (aset arr gt (aget arr i)) (aset arr i t) + (recur lt i (dec gt))) + :else (recur lt (inc i) gt))))))))) + (vec arr))))) (defn -main [] (let [input (slurp *in*) lines (clojure.string/split-lines input)