Skip to content

Commit d8ee069

Browse files
committed
Y2024D18
1 parent e7bd020 commit d8ee069

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

input/2024/input18.nippy

13.3 KB
Binary file not shown.

notebooks/y2024/d18.clj

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
(ns y2024.d18
2+
(:require
3+
[advent-of-code-clj.input :as input]
4+
[advent-of-code-clj.utils :as utils]
5+
[clojure.core.matrix :as mx]
6+
[ubergraph.alg :as ua]))
7+
8+
; # 2024, dag 18
9+
10+
; ## Del 1
11+
12+
; Test-inputten inneholder koordinater for noder som blokkerer en path fra [0 0] til [6 6].
13+
; Her kan vi bruke `ubergraph` sin shortest-path-algoritme, men først må vi hente ut riktig
14+
; antall blokkerende noder.
15+
16+
(def test-input "5,4
17+
4,2
18+
4,5
19+
3,0
20+
2,1
21+
6,3
22+
2,4
23+
1,5
24+
0,6
25+
3,3
26+
2,6
27+
5,1
28+
1,2
29+
5,5
30+
2,5
31+
6,5
32+
1,4
33+
0,4
34+
6,4
35+
1,1
36+
6,1
37+
1,0
38+
0,5
39+
1,6
40+
2,0")
41+
42+
; I parsingen reverserer vi X og Y for å bedre passe inn i matrisen vår.
43+
44+
(defn corrupted-locations [input]
45+
(->> input
46+
(re-seq #"\d+")
47+
(map parse-long)
48+
(partition 2)
49+
(map reverse)
50+
(map vec)))
51+
52+
(corrupted-locations test-input)
53+
54+
; Pathen kan finnes ved å hente nabo-noder og filtrere vekk noder som er "out of bounds",
55+
; og som er blokkert av `corrupted-locations`:
56+
57+
(defn find-path [[dimy dimx :as _dimensions] corrupted-locations]
58+
(let [in-bounds? (fn [[y x]]
59+
(and (>= dimy y 0)
60+
(>= dimx x 0)))]
61+
(ua/shortest-path
62+
(fn [node]
63+
(->> (apply utils/adjacent-hv node)
64+
(remove (some-fn corrupted-locations
65+
(complement in-bounds?)))
66+
(map (fn [x] {:dest x}))))
67+
[0 0] [dimy dimx])))
68+
69+
; Viktig å huske på at vi ikke skal ta inn alle nodene i input, så funksjonen vår kan
70+
; ta to argumenter for dimensjon og antall "bytes":
71+
72+
(defn part-1 [dimensions bytes input]
73+
(let [corrupted-locations (set (take bytes (corrupted-locations input)))]
74+
(:cost (find-path dimensions corrupted-locations))))
75+
76+
; Det gir oss følgende svar for del 1:
77+
78+
(delay (part-1 [6 6] 12 test-input))
79+
80+
(delay (part-1 [70 70] 1024 (input/get-input 2024 18)))
81+
82+
; For debugging har vi denne hjelpemetoden som printer ut matrisen:
83+
84+
(defn print-matrix [[y x :as dims] bytes input]
85+
(let [corrupted-nodes (set (take bytes (corrupted-locations input)))
86+
travel-path (set (ua/nodes-in-path (find-path dims corrupted-nodes)))]
87+
^:kind/hiccup
88+
[:pre
89+
(with-out-str
90+
(mx/pm (mx/emap-indexed (fn [node _]
91+
(cond
92+
(corrupted-nodes node) \#
93+
(travel-path node) \O
94+
:else \.))
95+
(mx/new-matrix (inc y) (inc x)))))]))
96+
97+
(delay (print-matrix [6 6] 12 test-input))
98+
99+
; ## Del 2
100+
101+
; I del 2 må vi finne ut hvilken node som vil føre til at det ikke er mulig å finne en
102+
; gyldig path til målet.
103+
104+
; Dette løser vi ved å snevre inn søkeområdet basert på om vi finner en gyldig path på
105+
; starten, midten og slutten av søkeområdet.
106+
107+
; (*TODO: denne algoritmen trenger litt refaktorering*)
108+
109+
(defn part-2 [dimensions input]
110+
(let [num-bytes (alength (.split input "\n"))
111+
corrupted-locations (corrupted-locations input)]
112+
(->> (nth corrupted-locations
113+
(loop [[start end] [0 num-bytes]]
114+
(if (>= 1 (- end start))
115+
(first (filter (fn [x]
116+
(find-path dimensions (set (take x corrupted-locations))))
117+
[start end]))
118+
(let [middle (int (+ (/ (- end start) 2) start))
119+
corrupted-locations-start (set (take start corrupted-locations))
120+
corrupted-locations-middle (set (take middle corrupted-locations))
121+
corrupted-locations-end (set (take end corrupted-locations))
122+
res-start (find-path dimensions corrupted-locations-start)
123+
res-middle (find-path dimensions corrupted-locations-middle)
124+
res-end (find-path dimensions corrupted-locations-end)]
125+
(cond
126+
(= nil res-end res-middle) (recur [start middle])
127+
(and res-start res-middle) (recur [middle end]))))))
128+
reverse
129+
(map str)
130+
(String/join ","))))
131+
132+
(delay (part-2 [6 6] test-input))
133+
(delay (part-2 [70 70] (input/get-input 2024 18)))

0 commit comments

Comments
 (0)