         :when (and (not (nil? neighbor-val)) (not= neighbor-val \#))]
     neighbor))
 
-(defn req-loc? [val] (and (not= val \.) (not= val \#)))
-
-(defn get-required-locations-count
-  [layout]
-  (->> layout
-       (filter (fn [[_ val]] (req-loc? val)))
-       (count)))
-
-(defn step
-  [layout visited-req-locations current-path-length shortest-path-length-so-far current-location req-locations-count prev-loc]
-  (println "Visiting" current-location)
-  (cond
-    (= (count visited-req-locations) req-locations-count) current-path-length
-    (= shortest-path-length-so-far current-path-length) shortest-path-length-so-far
-    :else
-      (let [next-locations (get-available-adjacent-locations layout current-location)
-            curr-value (get layout current-location)
-            next-req-locations (if (req-loc? curr-value) (conj visited-req-locations curr-value) visited-req-locations)]
-        (println "Got" (dec (count next-locations)) "locations next")
-        (reduce
-          (fn [shortest-so-far loc]
-            (step layout next-req-locations (inc current-path-length) shortest-so-far loc req-locations-count current-location))
-          shortest-path-length-so-far
-          (filter #(not= prev-loc %) next-locations)))))
-
-(def sample-input "###########\n#0.1.....2#\n#.#######.#\n#4.......3#\n###########")
-(def sample-layout (parse-input sample-input))
-(def start (find-start-location sample-layout))
+(defn traverse
+  [layout start-coord start-point known-distances]
+  (loop [locations [start-coord] visited #{} steps 1 distances known-distances]
+    (let [next-locations
+          (->> locations
+               (mapcat (partial get-available-adjacent-locations layout))
+               (filter #(not (contains? visited %)))
+               (distinct))
+          next-visited (apply conj visited locations)
+          next-steps (inc steps)
+          new-req-points
+          (->> next-locations
+               (map layout)
+               (filter req-point?)
+               (filter #(not (contains? distances [% start-point]))))
+          next-distances (apply conj distances (map (fn [loc] [[start-point loc] steps]) new-req-points))]
+      (if (empty? next-locations)
+        distances
+        (recur next-locations next-visited next-steps next-distances)))))
 
 
+(defn find-distances-between-req-points
+  [layout req-points]
+  (reduce (fn [acc point] (traverse layout (req-points point) point acc)) (hash-map) (keys req-points)))
 
-(get-available-adjacent-locations sample-layout [5 1])
+(defn get-distance
+  [distances from to]
+  (get distances [from to] (get distances [to from])))
 
-(step
-  sample-layout
-  #{}
-  0
-  12333
-  start
-  (get-required-locations-count sample-layout)
-  nil)+(defn find-shortest-path
+  [distances current-point all-points visited-points current-path min-known-path get-final-step]
+  (let [remaining-locations (clojure.set/difference all-points visited-points)]
+    (cond
+      (>= current-path min-known-path) min-known-path
+      (empty? remaining-locations) (min min-known-path (+ current-path (get-final-step current-point)))
+      :else (reduce
+              (fn [min-path point]
+                (find-shortest-path
+                  distances
+                  point
+                  all-points
+                  (conj visited-points point)
+                  (+ current-path (get-distance distances current-point point))
+                  min-path
+                  get-final-step))
+              min-known-path
+              remaining-locations))))
+
+(def input "#####################################################################################################################################################################################\n#.....#.#.....#.#.#...#.....#.#.#.#.....#3......#...........#.#.....#.....#.............#.#...#...#.....#...#.........#.#...............#.....#.....#.........................#.....#\n#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#####.#.#.#.#####.#.###.#.#.###.#.#####.###.#.#.#.#.#####.#.#.#.#####.#.#.#####.#.#.#####.###.#.#.###.###.###.#.###.#.###.###.#.#######.#######\n#.....#...#.#.....#...#.........#...........#.......#...#.#.....#.....#.#.#.......#...#.#...#...#...#.#...#...#.#...#.#.#.#.......#...#...#.....#.....#.....#...#...#.......#.#...#.#\n###.#####.#.#######.###.#.#.#.#.#.#####.#.#.#.#####.#.###.#.#####.#.#.#.#.#####.#.#.#.#.#.###.#.###.#.#####.#.#.#.#.###.#.#.#.###.#.#.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#.#####.#.#.#.#\n#...#1......#.....#.#.#.#.....#.#.#.....#...#.#...#.......#...........#.............#...#.....#.......#.....#.....#.#.......#.#...#.#.#.#.......#...#.#...........#.#.....#...#.#...#\n#.#.###.#.###.#.#.#.#.#.#.#######.#.#.###.#.#.#.###.#####.###.#.#.#.#.#.###.#.#####.#.#.#####.#####.#.#.#.#.#.#.#.###.###.#.#####.#.#.#####.#.#.#.#.#.#.#.###.#####.###.#.#.#.#.###.#\n#.....#.#.....#.#...#.#.....#.#.#.#.........#.#.#.......#.#.#.......#...#...#...#.....#.#...#.......#.....#.......#...#.....#...#...#.......#...#.#.....#...#.#.....#.#...#.#...#...#\n#.#.#.#.#####.#.###.#.#.#.###.#.###.#.#.#####.#.#####.#.#.#.#.#####.#.#.#.###.#######.#.###.#.###.#.#.#.#.#.#.#####.###.#####.#.#.#.#.#####.#####.#.###.#.#.#.#.#.#.#.#####.###.#.###\n#...#.#...#.........#.#...#.#...#.....#.#.....#.......#.........#.....#.....#.........#.....#...#.#.#.#.....#.#.................#.#.#.......#.......#.......#...#...#.......#.#...#.#\n#.#.#.#.#.#.#.###.#.###.###.#.#.#.###.###.#.#.#.#.#.#.#########.#.###.#.#.#####.#.#.#.###.#######.#.###.#.#.#.#.#.#.#.###.#.#.###.#######.#.###.#.#.#.#.###.#.#.#.#####.###.#.#.###.#\n#...#.#.#.#.#...#...#...#.............#.....#.....#...#...#.#.....#...#...#.....#.#.....#...#...........#.#.#.#.......#...#.............#...#.#...#...........#...#2#...#.....#.#.#.#\n###.###.#.#####.#.#.#.#.#.#.#.#.#.#.###.###.#.#.#.###.###.#.#.#.#.#.#.###.###.#.#.#.#.###.#.#.#.###.#####.###.###.#.#.#.###.#######.###.###.#.#.#.#####.#####.###.#.#.#####.#.#.#.###\n#.......#...#...........#.......#...#.#.......#.....#.....#...#...#.#.........#.......#...#.#...#...........#.#...#.#...............#.#.#.....#.......#.#.#.#.....#.........#.#.#.#.#\n###.#.#.#.#.#.#.#####.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#####.#.###.#.###.#.#.#.#########.###.#.###.#.###.#.#.#.#.#######.#####.###.#.#.#.#.#####.#####.#.#.#.#.#.#######.#.###.#.#.#.#\n#...#.....#.#.............#...#.#.....#.#...#.......#.........#...#...#.#...#...........#...#...........#...#...#.................#...#.#.#.....#.......#.#.#.......#...#...#...#...#\n###.#.#######.#.#.#.###.#.#.#.###.#.#.#.#.#.###.#####.#.###.#.#.#.###.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#####.#.#####.#.#.#.#.#.#######.#.#.#.###.#.#.#.#.#.###.#.###.#########.###.#.#.#\n#.....#...#.....#.....#...#.........#.#...#.....#...#.................#...#.#.#.......#.....#...#.#.................#.#.#.........#.....#...#.#...#.....#.................#.#.....#.#\n#.#####.#.#.#####.###.#.#.#.###.###.#.#########.#.#######.###.###.#.#.#.#.#.#.#.###.#.#.#####.#.###.#.#########.#.###.###.#.###.###.#.#.#.#.#.###.#####.#.#.#######.#.###.#.#.###.###\n#0#...#.#...#...........#.#.............#.#.......#.....#.#.#.....#.#.#...#.....#.#.#.......#.#...#.................#.#.#.....#...#.#.........#.......#.#...#.......#.......#.....#.#\n#####.#.###.#.#.###.#####.###.#######.###.#.#.###.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#####.###.#.#####.#.#.#.###.#.#.#.#########.#.#.#.###.#.#.###.#.#####.#.#.#.#.#.###.###.#.#.#.#\n#...#.#.....#.#.#...#.......#.#.#...#.........#.......#...#.#.....#.............#...........#...#.#.......#.#.....#.#...........#...#.........#.#...#.#.....#.......#...#.......#...#\n###.###.###.#.###.###.#.###.###.#.#.#.#########.#####.###.#######.#.###.#.#.#.###.#.#.#.#.#.#.#.#####.###.#.#.#.#.#.#.#####.###.#.#.###.#####.#.#.#####.#.#.###.#.#####.#.#.#.#.#.#.#\n#.......#...............#.....#...#...#.#...#.........#...........#.....#.....#.......#...#.....#.......#.#.#.#...#...............#.....#.....#...#.#...#...#.#.#.#.#.....#...#.#.#4#\n#.#.#.#.#.#####.###.#.#####.#.###.#.###.#.#.#.###.###.#.#####.#.#####.#.#######.#.#####.#.#######.#.###.#.#.#.###.###.###.#####.#.###.#.#.#.#####.#.#.#.###.#.#.###.###.#.#.#.#.#.###\n#...#...........#.......#...#.....#.#.......#.....#.........#.#.......#.#...#...#...........#.......#.....#...#...#...#.#...#.....#...#.........#...#...#.....#.....#...#...#...#...#\n###.#.###.#############.#.###.###.#.###.#.#.#.#.#.#.#.#.###.#####.#.#.#.#.#.#####.###.#.#.#.#.###.#.#.#.#.#.###.#.#.###.#.#.#.###.###.#.#.###.#.#.#.#.#.#.#####.#.#.#.#.#.#.###.#.###\n#...#.....#.#...#.#.#.#...........#.......#...#.....#...#...................#...#...#.#.#.#...#.......#...............#...#...#...#...#.#.#5#...#...#.#...#...#.#...#.#...#...#.#...#\n#.###.###.#.#.#.#.#.#.###.#.#######.#.#.#.###.#.#.#.#.#.#.###.#.###.###.#.#.#.#.#.###.#.#.#.#.#.###.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#####.#.#.#######.#.#.#.#.#.#####.#.#######.#.#.#\n#.........#.#...#.#...#...#.............#.....#...#.#.#.#.#.#.....#.#...#.....#.#.#.........#.....#.........#.....#...........#...#.........#.....#...#.#.#.#...#...........#...#...#\n#.#.#.#######.#.#####.#.#.#.###.#.#######.#####.#.#.###.#.#.#.###.###.#.###.#.#.#.###.#.#.#.#####.#.###.#.#.#.#.#.#.#####.#.#.###.#.#.#.#.#####.###.#####.#.#.#.#.###.#.#.#####.#####\n#...#...............#.#.......#.......#.......#.........#.#.#.#...#...#...#.......#.#.....#.#...........#...#.#.#...........#.#...#.......#.........#...#...#.....#...#.#.....#.#...#\n###.#.#.#.#.#########.#.#.#.#.#.#####.#.#######.#.###.#.#.#.###.###.#.#.#.#.#.###.#.#.###.#.#####.#.###########.#.#.#####.#####.#####.#####.#.#.#.#.#.#.#####.#.#.#########.#.###.#.#\n#.#...#.....#.......#.....#...#.......#.#.#...#...#...#.........#...#...#.#...#.#.........#.#.......#.#.#...#...#.........#.#.........#.....#.#.#...#.......#.#.....#.......#.#.....#\n#.#.###.#.###.#.#.#.#.###.#########.#.#.#.#.#.#.###.#.#.#####.#.#.#####.#####.#.#.#########.#.#.#.###.#.#####.#.#.###.###.#.#.#.#.#.#####.###.#.###########.#.#.#.#.#.#######.#####.#\n#........7#.....#.#...#.#.#.#.........#...#.#...........#.....#.......#.........#.........#.....#.......#.#.......#.#.#...#...#.#.#....6#.#.........................#...#.#.......#.#\n#.###.#.###.###.###.#.#.###.###.#####.###.#.#.###.#####.###.#.###.#.#.#.#.#.#.#.#.#####.#.#.#####.#######.#.###.#.#.#####.#####.#.#.#.###.#.#.#.#.#####.#.#.###.#####.#.#.#.#.#.#.#.#\n#.#...#.#...#.#.....#.#.......#...#.....#...#...#...#...#.#.....#...#.#...#...#...#.#.............#.............#.#...#.............#.#.....#.....#.......#.#.#.#.........#...#...#.#\n#####################################################################################################################################################################################")
+(def layout (parse-input input))
+(def req-points (find-req-points layout))
+(def distances (find-distances-between-req-points layout req-points))
+
+(println "Part 1:" (find-shortest-path
+                     distances
+                     \0
+                     (into (hash-set) (keys req-points))
+                     #{\0}
+                     0
+                     Integer/MAX_VALUE
+                     (constantly 0)))
+
+(println "Part 2:" (find-shortest-path
+                     distances
+                     \0
+                     (into (hash-set) (keys req-points))
+                     #{\0}
+                     0
+                     Integer/MAX_VALUE
+                     (partial get-distance distances \0)))
+

(ns advent-of-code-2016.day24)

(defn parse-input
  [input]

         (fn [row-number row]
           (map-indexed (fn [column-number symbol] [[column-number row-number] symbol]) row)))
       (apply concat)
       (into (hash-map))))

(defn find-req-points
  [layout]
  (->> layout
       (filter (fn [[_ symbol]] (req-point? symbol)))
       (map (comp vec reverse))
       (into (hash-map))))

(defn get-available-adjacent-locations
  [layout [x y]]
