day15: priority queue, <10 sec

master
Clyne 3 years ago
parent 9d83aa4f3c
commit fa34a065ee

@ -1,5 +1,3 @@
(require '[clojure.core.reducers :as r])
(def input (->> (slurp "./in") (def input (->> (slurp "./in")
(clojure.string/split-lines) (clojure.string/split-lines)
(mapv (partial mapv (comp read-string str))) (mapv (partial mapv (comp read-string str)))
@ -7,38 +5,26 @@
{[y x] (get-in % [y x])})) {[y x] (get-in % [y x])}))
(into {}))) (into {})))
(defn min-distance [dist Q] (def dim (apply max (map first (keys input))))
(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] (defn find-neighbors [u]
(filter #(contains? Q %) [(update u 0 inc) (filter #(contains? input %) [(update u 0 inc)
(update u 0 dec) (update u 0 dec)
(update u 1 inc) (update u 1 inc)
(update u 1 dec)])) (update u 1 dec)]))
(let [dim (apply max (map first (keys input)))] (loop [dist (zipmap (keys input) (repeat ##Inf))
(loop [Q (apply sorted-set (keys input)) Q {[0 0] 0}]
dist (assoc (hash-map) [0 0] 0)] (if (empty? Q)
(when (= 0 (rem (count Q) 500)) (println (count Q))) (println (dist [dim dim]))
(if (empty? Q) (let [[u distu] (first Q)
(println (dist [dim dim])) NN (reduce
(let [[u vu] (min-distance dist Q)] #(let [dv (+ distu (input %2))]
(recur (cond-> %1
(disj Q vu) (> ((first %1) %2) dv)
(reduce (-> (update 0 assoc %2 dv)
#(let [alt (+ u (input %2))] (update 1 assoc %2 dv))))
(cond-> %1 [dist {}]
(or (not (contains? dist %2)) (< alt (dist %2))) (find-neighbors u))]
(assoc %2 alt))) (recur (first NN) (sort-by val < (into (rest Q) (second NN)))))))
dist
(find-neighbors Q vu)))))))

@ -1,5 +1,3 @@
(require '[clojure.core.reducers :as r])
(def input (->> (slurp "./in") (def input (->> (slurp "./in")
(clojure.string/split-lines) (clojure.string/split-lines)
(mapv (partial mapv (comp read-string str))) (mapv (partial mapv (comp read-string str)))
@ -18,37 +16,26 @@
(into {}) (into {})
)) ))
(defn min-distance [dist Q] (def dim (apply max (map first (keys input))))
(r/fold
(r/monoid (defn find-neighbors [u]
#(if (< (first %1) (first %2)) %1 %2) (filter #(contains? input %) [(update u 0 inc)
(constantly [##Inf []])) (update u 0 dec)
(r/monoid (update u 1 inc)
#(if (< (first %1) (dist %2)) %1 [(dist %2) %2]) (update u 1 dec)]))
(constantly [##Inf []]))
(r/filter
(partial contains? dist)
(apply vector Q))))
(defn find-neighbors [Q u] (loop [dist (zipmap (keys input) (repeat ##Inf))
(filter #(contains? Q %) [(update u 0 inc) Q {[0 0] 0}]
(update u 0 dec) (if (empty? Q)
(update u 1 inc) (println (dist [dim dim]))
(update u 1 dec)])) (let [[u distu] (first Q)
NN (reduce
#(let [dv (+ distu (input %2))]
(cond-> %1
(> ((first %1) %2) dv)
(-> (update 0 assoc %2 dv)
(update 1 assoc %2 dv))))
[dist {}]
(find-neighbors u))]
(recur (first NN) (sort-by val < (into (rest Q) (second NN)))))))
(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)))))))

Loading…
Cancel
Save