diff --git a/day15/part1.clj b/day15/part1.clj index 48dab23..caf4e2c 100644 --- a/day15/part1.clj +++ b/day15/part1.clj @@ -1,3 +1,5 @@ +(require '[clojure.core.reducers :as r]) + (def input (->> (slurp "./in") (clojure.string/split-lines) (mapv (partial mapv (comp read-string str))) @@ -6,13 +8,16 @@ (into {}))) (defn min-distance [dist Q] - (reduce - #(if (and (not= (dist %2) :inf) - (or (= :inf (first %1)) - (< (dist %2) (first %1)))) - [(dist %2) %2] - %1) - [:inf []] Q)) + (r/fold + (r/monoid + #(if (< (first %1) (first %2)) %1 %2) + (constantly [##Inf []])) + (r/monoid + #(if (< (first %1) (dist %2)) %1 [(dist %2) %2]) + (constantly [##Inf []])) + (r/filter + (partial contains? dist) + (apply vector Q)))) (defn find-neighbors [Q u] (filter #(contains? Q %) [(update u 0 inc) @@ -21,22 +26,19 @@ (update u 1 dec)])) (let [dim (apply max (map first (keys input)))] - (loop [Q (set (keys input)) - dist (-> (zipmap Q (repeat :inf)) (update [0 0] #(do % 0)))] + (loop [Q (apply sorted-set (keys input)) + dist (assoc (hash-map) [0 0] 0)] + (when (= 0 (rem (count Q) 500)) (println (count Q))) (if (empty? Q) (println (dist [dim dim])) (let [[u vu] (min-distance dist Q)] (recur (disj Q vu) - (loop [d dist f (find-neighbors Q vu)] - (if (empty? f) - d - (recur - (let [v (first f) alt (+ u (input v))] - (if (or (= :inf (dist v)) (< alt (dist v))) - (assoc d v alt) - d - )) - (rest f) - )))))))) + (reduce + #(let [alt (+ u (input %2))] + (cond-> %1 + (or (not (contains? dist %2)) (< alt (dist %2))) + (assoc %2 alt))) + dist + (find-neighbors Q vu))))))) diff --git a/day15/part2.clj b/day15/part2.clj index d48ba92..1b2b409 100644 --- a/day15/part2.clj +++ b/day15/part2.clj @@ -1,3 +1,5 @@ +(require '[clojure.core.reducers :as r]) + (def input (->> (slurp "./in") (clojure.string/split-lines) (mapv (partial mapv (comp read-string str))) @@ -17,15 +19,16 @@ )) (defn min-distance [dist Q] - (reduce - #(if (and (not= (dist %2) :inf) - (or (= :inf (first %1)) - (< (dist %2) (first %1)))) - [(dist %2) %2] - %1) - [:inf []] - Q - )) + (r/fold + (r/monoid + #(if (< (first %1) (first %2)) %1 %2) + (constantly [##Inf []])) + (r/monoid + #(if (< (first %1) (dist %2)) %1 [(dist %2) %2]) + (constantly [##Inf []])) + (r/filter + (partial contains? dist) + (apply vector Q)))) (defn find-neighbors [Q u] (filter #(contains? Q %) [(update u 0 inc) @@ -33,22 +36,19 @@ (update u 1 inc) (update u 1 dec)])) -(loop [Q (set (keys input)) - dist (-> (zipmap Q (repeat :inf)) (update [0 0] #(do % 0)))] - (if (empty? Q) - (println (dist [499 499])) - (let [[u vu] (min-distance dist Q)] - (recur - (disj Q vu) - (loop [d dist f (find-neighbors Q vu)] - (if (empty? f) - d - (recur - (let [v (first f) alt (+ u (input v))] - (if (or (= :inf (dist v)) (< alt (dist v))) - (assoc d v alt) - d - )) - (rest f) - ))))))) - +(let [dim (apply max (map first (keys input)))] + (loop [Q (apply sorted-set (keys input)) + dist (assoc (hash-map) [0 0] 0)] + (when (= 0 (rem (count Q) 500)) (println (count Q))) + (if (empty? Q) + (println (dist [dim dim])) + (let [[u vu] (min-distance dist Q)] + (recur + (disj Q vu) + (reduce + #(let [alt (+ u (input %2))] + (cond-> %1 + (or (not (contains? dist %2)) (< alt (dist %2))) + (assoc %2 alt))) + dist + (find-neighbors Q vu)))))))