Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit efc3763

Browse files
committed
day15: Oxygen System
1 parent 4716711 commit efc3763

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed

resources/day15_input.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1002,1034,1,1039,102,1,1036,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1002,1034,1,1039,101,0,1036,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,102,1,1035,1040,1002,1038,1,1043,1002,1037,1,1042,1106,0,124,1001,1034,1,1039,1008,1036,0,1041,1002,1035,1,1040,101,0,1038,1043,1002,1037,1,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,9,1032,1006,1032,165,1008,1040,3,1032,1006,1032,165,1102,2,1,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1101,1,0,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,29,1044,1105,1,224,1101,0,0,1044,1105,1,224,1006,1044,247,102,1,1039,1034,1002,1040,1,1035,1001,1041,0,1036,1002,1043,1,1038,102,1,1042,1037,4,1044,1106,0,0,19,27,41,9,17,87,2,1,91,14,15,99,17,13,40,13,7,33,23,28,7,21,75,15,41,83,18,4,28,1,21,99,3,2,4,60,16,5,16,22,59,18,37,21,62,96,11,63,46,16,27,76,7,36,38,28,53,18,84,52,12,47,25,93,10,57,64,21,41,75,52,9,80,60,21,86,60,21,70,21,13,72,78,22,61,17,28,54,51,93,18,3,87,21,4,98,17,59,2,17,18,71,5,20,16,39,66,18,7,62,15,37,25,52,27,17,15,10,48,11,39,18,20,68,83,22,36,9,3,69,56,64,21,39,93,1,90,18,57,52,14,41,32,57,5,7,72,18,35,66,21,22,88,2,31,52,7,35,25,50,14,35,7,11,92,38,14,66,3,28,84,18,17,48,15,34,40,4,21,92,52,27,5,4,53,65,59,24,88,24,66,88,85,26,8,26,10,64,99,9,44,38,14,26,74,75,24,31,7,6,62,9,57,75,18,22,52,57,15,3,87,21,39,24,12,8,70,8,19,3,89,16,36,15,36,16,30,28,8,89,12,99,98,16,78,24,11,63,87,55,51,19,57,18,28,9,90,15,95,56,57,1,93,77,24,36,14,44,46,25,66,37,23,8,12,10,58,27,66,4,72,1,2,16,91,16,66,26,24,53,25,20,41,8,75,23,2,20,91,19,3,12,32,30,3,33,85,17,21,92,17,1,12,73,9,34,12,85,42,5,69,67,4,87,70,6,49,96,12,5,37,62,54,72,13,52,14,21,84,68,54,22,78,11,93,12,90,55,7,19,44,21,98,4,46,50,27,30,2,99,27,35,8,5,62,1,91,65,12,80,16,17,81,14,73,60,69,24,23,13,74,57,10,26,21,80,60,10,79,3,9,37,77,73,16,10,3,13,95,4,91,65,11,86,16,24,71,22,6,63,90,56,15,64,8,25,46,77,71,24,13,72,96,22,8,15,79,39,19,19,47,14,16,92,69,73,23,76,23,28,60,84,14,54,62,11,8,30,75,44,16,4,30,82,14,80,11,1,70,85,10,14,73,70,9,54,25,26,12,51,23,86,92,18,11,19,74,55,51,10,73,7,13,43,89,5,55,2,18,82,2,14,63,71,28,7,94,61,10,51,8,53,63,22,39,19,79,20,99,2,66,22,7,68,71,17,19,45,10,14,42,99,9,9,13,75,84,14,83,75,19,92,22,47,4,83,18,46,91,22,61,28,6,71,17,10,1,81,6,60,83,21,14,13,71,11,68,73,52,10,25,30,91,6,25,86,89,19,39,18,95,1,52,23,91,20,14,41,91,26,59,16,85,99,4,15,96,51,19,25,51,73,3,48,79,14,14,41,5,17,59,8,51,43,21,15,47,3,28,53,12,22,23,2,94,74,23,53,20,20,98,21,14,46,61,26,6,55,20,69,28,6,41,19,70,48,6,9,32,32,28,20,21,62,22,38,7,90,3,32,24,92,49,23,72,63,17,18,89,85,33,28,23,27,5,42,52,7,54,18,17,21,63,98,8,9,84,31,24,80,70,22,51,28,61,77,6,25,68,66,8,47,22,7,44,26,37,15,28,68,23,18,18,14,34,3,85,99,31,41,53,28,20,43,90,22,13,70,27,27,17,35,48,11,92,4,60,84,4,38,27,25,89,99,74,2,31,63,13,50,1,54,4,59,3,59,2,54,15,37,19,74,45,75,7,84,19,96,72,75,9,34,18,52,23,99,11,45,81,53,7,71,24,80,26,31,11,74,27,57,0,0,21,21,1,10,1,0,0,0,0,0,0
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
(ns clj-adventofcode-2019.day15
2+
(:require
3+
[clojure.set]
4+
[clj-adventofcode-2019.intcode :as intcode]
5+
))
6+
7+
(def robot-control-program (intcode/load-program-from-resource "day15_input.txt"))
8+
9+
(def directions {:north 1
10+
:south 2
11+
:west 3
12+
:east 4})
13+
14+
(def status-codes {0 :wall
15+
1 :moved
16+
2 :moved-on-target
17+
-1 :unknown})
18+
19+
(defn calc-new-pos [last-pos previous-direction]
20+
(case previous-direction
21+
:north [(first last-pos) (inc (second last-pos))]
22+
:south [(first last-pos) (dec (second last-pos))]
23+
:west [(dec (first last-pos)) (second last-pos)]
24+
:east [(inc (first last-pos)) (second last-pos)]))
25+
26+
(defn four-neighbours [coord]
27+
(for [d (keys directions)]
28+
(calc-new-pos coord d)))
29+
30+
(defn calc-direction [next-pos current-pos]
31+
(let [v [(- (first next-pos) (first current-pos))
32+
(- (second next-pos) (second current-pos))]]
33+
(case v
34+
[1 0] :east
35+
[-1 0] :west
36+
[0 1] :north
37+
[0 -1] :south
38+
:else (throw (AssertionError. (str "Wrong next-pos" next-pos current-pos))))))
39+
40+
41+
(defn add-coordinate-to-area [area coordinate status]
42+
(let [additional-coordinates (if (or (= status :moved)
43+
(= status :moved-on-target)
44+
)
45+
(into [] (for [n (four-neighbours coordinate) :when (not (contains? area n))]
46+
[n :unknown]))
47+
[])]
48+
(into area (conj additional-coordinates [coordinate status]))
49+
)
50+
)
51+
52+
(comment
53+
(add-coordinate-to-area {} [0 0] :moved)
54+
;; => {[0 1] :unknown, [0 -1] :unknown, [-1 0] :unknown, [1 0] :unknown, [0 0] :moved}
55+
56+
(add-coordinate-to-area {[0 1] :unknown
57+
[0 -1] :unknown
58+
[-1 0] :unknown
59+
[1 0] :unknown
60+
[0 0] :moved}
61+
[0 1] :wall)
62+
63+
;; => {[0 1] :wall, [0 -1] :unknown, [-1 0] :unknown, [1 0] :unknown, [0 0] :moved}
64+
)
65+
66+
(defn is-spot-reachable [spot]
67+
(let [[_ status] spot]
68+
(or (= status :moved)
69+
(= status :moved-on-target))
70+
))
71+
72+
(defn only-reachable-spots-of [area]
73+
(filter is-spot-reachable area)
74+
)
75+
76+
(comment
77+
(only-reachable-spots-of {[0 1] :wall, [0 -1] :unknown, [-1 0] :unknown, [1 0] :unknown, [0 0] :moved})
78+
;; => ([[0 0] :moved])
79+
)
80+
81+
82+
83+
(def infinity Integer/MAX_VALUE)
84+
;; => #'clj-adventofcode-2019.day15/infinity
85+
86+
87+
(defn shortest-path [coordinates source destination]
88+
(let
89+
[get-min-dist (fn [dist-map] (ffirst (sort-by (fn [[_ v]] (:dist v)) dist-map)))
90+
get-neighbours (fn [coordinate-set c] (clojure.set/intersection
91+
(set (four-neighbours c))
92+
coordinate-set))
93+
calc-dist-prev (fn [dist-map u n]
94+
(let [new-dist (inc (:dist (get dist-map u)))
95+
old-dist (:dist (get dist-map n))]
96+
(if (< new-dist old-dist) {:dist new-dist :prev u}
97+
(get dist-map n))))
98+
dijkstra-dist-map (loop [vertex-set (set coordinates)
99+
dist-map (assoc (into {} (for [c coordinates]
100+
[c {:dist infinity :prev :unknown}]))
101+
source {:dist 0 :prev :unknown})]
102+
(if (empty? vertex-set)
103+
dist-map
104+
(let [u (get-min-dist (filter (fn [[k _]] (contains? vertex-set k)) dist-map))
105+
new-vertex-set (disj vertex-set u)
106+
neighbours (get-neighbours new-vertex-set u)
107+
new-dist-map (into dist-map (for [n neighbours] [n (calc-dist-prev dist-map u n)]))]
108+
;(println (str u new-vertex-set neighbours new-dist-map))
109+
(recur new-vertex-set new-dist-map))))
110+
111+
build-path (fn [dist-map source destination path]
112+
(if (= source destination) path
113+
(recur dist-map source (:prev (get dist-map destination)) (conj path destination))))]
114+
(build-path dijkstra-dist-map source destination '())
115+
116+
))
117+
118+
119+
(comment
120+
(shortest-path [[0 0]
121+
[-1 0] [-2 0] [-2 1] [-2 2] [-2 3] [-1 3]
122+
[0 1] [0 2] [0 3]
123+
]
124+
[0 0]
125+
[0 3])
126+
;; => ([0 1] [0 2] [0 3])
127+
128+
129+
)
130+
131+
132+
133+
(defn distance-between [c1 c2]
134+
(+ (Math/abs (- (first c1) (first c2)))
135+
(Math/abs (- (second c1) (second c2)))))
136+
137+
(comment
138+
(distance-between [10 10] [5 5])
139+
;; => 10
140+
(distance-between [1 0] [2 0])
141+
;; => 1
142+
(distance-between [1 0] [2 1])
143+
;; => 2
144+
)
145+
146+
(defn nearest-unknown-position [area current-pos]
147+
(let [all-unknown (map first (filter (fn [[_ v]] (= v :unknown)) area))]
148+
(first (sort-by (partial distance-between current-pos) all-unknown))))
149+
150+
(comment
151+
(nearest-unknown-position (add-coordinate-to-area {} [0 0] :moved) [0 0])
152+
;; => [0 1]
153+
(nearest-unknown-position {} [0 0])
154+
;; => nil
155+
)
156+
157+
(defn calc-next-direction [area current-pos]
158+
(let [target-position (nearest-unknown-position area current-pos)]
159+
(if (nil? target-position)
160+
nil
161+
(let [path-to-target (shortest-path (conj (map first (only-reachable-spots-of area)) target-position)
162+
current-pos
163+
target-position)
164+
next-pos (first path-to-target)]
165+
(calc-direction next-pos current-pos)))))
166+
167+
168+
169+
(comment
170+
(calc-next-direction (add-coordinate-to-area {} [0 0] :moved) [0 0])
171+
;; => :north
172+
(calc-next-direction {[0 0] :moved} [0 0])
173+
;; => nil
174+
(calc-next-direction {[0 0] :moved [0 1] :unknown} [0 0])
175+
;; => :north
176+
(calc-next-direction {[0 0] :moved [0 -1] :unknown} [0 0])
177+
;; => :south
178+
(calc-next-direction {[0 0] :moved [1 0] :unknown} [0 0])
179+
;; => :east
180+
(calc-next-direction {[0 0] :moved [-1 0] :unknown} [0 0])
181+
;; => :west
182+
)
183+
184+
(def initial-program-state (intcode/initialize-and-run robot-control-program))
185+
186+
(defn move-robot-until-target-found
187+
([] (let [after-first-move
188+
(intcode/run (assoc initial-program-state
189+
:input [(directions :north)]))]
190+
(move-robot-until-target-found after-first-move {[0 0] :moved} :north [0 0])))
191+
([program-state area previous-direction last-pos]
192+
(let [status-code (get status-codes (first (:output program-state)))
193+
new-pos (calc-new-pos last-pos previous-direction)
194+
new-area (add-coordinate-to-area area new-pos status-code)
195+
current-pos (if (= status-code :wall) last-pos new-pos)
196+
new-direction (calc-next-direction new-area current-pos)]
197+
(if (nil? new-direction)
198+
{:area new-area :pos current-pos}
199+
(case status-code
200+
(:moved :wall) (recur (intcode/run (assoc program-state
201+
:input [(directions new-direction)]
202+
:output []))
203+
new-area
204+
new-direction
205+
current-pos)
206+
207+
208+
:moved-on-target {:area new-area :pos current-pos})))))
209+
210+
211+
(defn move-robot-to-every-spot
212+
([] (let [after-first-move
213+
(intcode/run (assoc initial-program-state
214+
:input [(directions :north)]))]
215+
(move-robot-to-every-spot after-first-move {[0 0] :moved} :north [0 0])))
216+
([program-state area previous-direction last-pos]
217+
(let [status-code (get status-codes (first (:output program-state)))
218+
new-pos (calc-new-pos last-pos previous-direction)
219+
new-area (add-coordinate-to-area area new-pos status-code)
220+
current-pos (if (= status-code :wall) last-pos new-pos)
221+
new-direction (calc-next-direction new-area current-pos)]
222+
(if (nil? new-direction)
223+
{:area new-area :pos current-pos}
224+
(recur (intcode/run (assoc program-state
225+
:input [(directions new-direction)]
226+
:output []))
227+
new-area
228+
new-direction
229+
current-pos)))))
230+
231+
(def full-area-map (:area (move-robot-to-every-spot)))
232+
233+
(comment
234+
(def target-pos (first (filter (fn [[_ v]] (= v :moved-on-target)) full-area-map)))
235+
;; => #'clj-adventofcode-2019.day15/target-pos
236+
target-pos
237+
;; => [[-12 18] :moved-on-target]
238+
(count (shortest-path (map first (only-reachable-spots-of full-area-map)) [0 0] [-12 18]))
239+
;; => 366 ; part 1 solution
240+
)
241+
242+
(comment
243+
; part 2
244+
(def all-reachable-spots (map first (only-reachable-spots-of full-area-map)))
245+
246+
(defn shortest-path-length-for [coordinates source destination]
247+
(count (shortest-path coordinates source destination)))
248+
249+
(last (sort (for [spot all-reachable-spots] (shortest-path-length-for all-reachable-spots [-12 18] spot))))
250+
;; => 384 ; part 2 solution
251+
)

0 commit comments

Comments
 (0)