[:require [adventofcode2019.lib :refer :all]
[clojure.string :as str]])
-;; FIXME: is the input guaranteed in-order?
(defn a-orbits-b [orbits-map [b a]]
(if (contains? orbits-map b)
- (-> (assoc orbits-map a {:parent b, :children [], :depth (inc (:depth b))})
+ (-> (assoc orbits-map a {:parent b, :children (get-in orbits-map [a :children] [])})
(update-in [b :children] conj a))
- (-> (assoc orbits-map b {:parent nil, :children [], :depth 0})
+ (-> (assoc orbits-map b {:parent nil, :children []})
(a-orbits-b [b a]))))
+(defn distances-from [tree node]
+ (letfn [(path-rc [dist tree node]
+ (let [seen? #(some? (get-in tree [% :dist]))
+ neighbors (remove (some-fn nil? seen?)
+ (cons (get-in tree [node :parent])
+ (get-in tree [node :children])))]
+ (as-> tree it
+ (assoc-in it [node :dist] dist)
+ (reduce #(path-rc (inc dist) %1 %2) it neighbors))))]
+ (path-rc 0 tree node)))
+
+(defn assign-depth [tree]
+ (let [is-root? #(nil? (get-in tree [% :parent]))
+ root (first (filter is-root? (keys tree)))]
+ (letfn [(depth-rc [depth tree root]
+ (as-> tree it
+ (assoc-in it [root :depth] depth)
+ (reduce #(depth-rc (inc depth) %1 %2)
+ it (get-in tree [root :children]))))]
+ (depth-rc 0 tree root))))
+
(defn day06 []
- (let [input (map #(str/split % #")") (get-list-from-file (input-file)))
- orbits-map (reduce a-orbits-b {} input)]
- (part1 (reduce + (map :depth orbits-map)))
- #_(part2)))
+ (let [input (map #(str/split % #"\)") (get-list-from-file (input-file)))
+ orbits-map (reduce a-orbits-b {} input)
+ with-depths (assign-depth orbits-map)]
+ (part1 (reduce + (map :depth (vals with-depths))))
+ (part2 (- (get-in (distances-from orbits-map "YOU") ["SAN" :dist]) 2))))