Fix day6pt1 and add correct day6pt2
[adventofcode2019.git] / src / adventofcode2019 / day06.clj
index 1d67336dface1692472d25e4d1ea4c5ea91328b8..928869288f21f81904806631ab243fadbdebed2a 100644 (file)
@@ -2,16 +2,37 @@
     [: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))))