day12: fast, parallel part 2

master
Clyne 3 years ago
parent c507675805
commit c999ec8124

@ -1,48 +1,50 @@
(require '[clojure.string :as str]) (require '[clojure.string :as str])
(require '[clojure.core.reducers :as r])
; Build list of cave connections: ; Build list of cave connections:
(def caves (->> (slurp "./in") (def caves (->> (slurp "./in")
(str/split-lines) (str/split-lines)
(map #(str/split % #"-")) (map #(str/split % #"-"))
(map (partial map str)) (map (partial map str))
(#(concat % (map reverse %))) (#(concat % (map reverse %)))
)) ))
; Try to help execution speed by memoizing cave searches: ; Try to help execution speed by memoizing cave searches:
(def search-caves (def search-caves
(memoize (fn [id] (memoize (fn [id]
(filter #(= (first %) id) caves)))) (filter
#(and (= (first %) id)
(not (str/starts-with? (second %) "start")))
caves
))))
; Given current path 'path', return a list of valid paths that branch ; Given current path 'path', return a list of valid paths that branch
; from 'path'. Note, paths are stored in reverse order. ; from 'path'. Note, paths are stored in reverse order.
(defn get-caves-forward [path] (defn get-caves-forward [path]
(map #(cons (second %) path) (r/map #(cons (second %) path)
(filter (r/filter
(fn [cv] (fn [cv]
(and (or
; Do not return to start ; Always allow uppercase paths
(not (str/starts-with? (second cv) "start")) (< (int (first (second cv))) 96)
(or ; Or, allow lowercase paths that have never been visited
; Always allow uppercase paths (not-any? #(= % (second cv)) path)
(< (int (first (second cv))) 96) ; Or, allow one duplicate if there are none yet
(let [lw (filter #(= (str/lower-case %) %) path)] (apply distinct? (filter #(= (str/lower-case %) %) path))))
(or ; Only work with paths that we connect to
; Allow lowercase paths that have never been visited (search-caves (first path))
(= 0 (count (filter #(= % (second cv)) path))) )))
; Allow one duplicate if there are none yet
(= 0 (- (count lw) (count (distinct lw)))))))))
; Only work with paths that we connect to
(search-caves (first path))
)))
(loop [paths (get-caves-forward ["start"]) complete-paths []] (loop [paths (into [] (get-caves-forward ["start"])) complete-paths 0]
(let [branches (->> paths (let [results (->> paths
(map get-caves-forward) (r/mapcat get-caves-forward)
(apply concat)) (r/foldcat)
complete-branches (concat complete-paths (r/reduce
(filter #(= (first %) "end") branches)) (fn [r b] (if (not= (first b) "end")
next-paths (filter #(not= (first %) "end") branches)] (update r :next-paths #(conj % b))
(if (empty? next-paths) (update r :complete-counts inc)))
(println (count complete-branches)) {:next-paths [] :complete-counts complete-paths}))]
(recur next-paths complete-branches)))) (println (results :complete-counts))
(when-not (empty? (results :next-paths))
(recur (results :next-paths) (results :complete-counts)))))

Loading…
Cancel
Save