1
1
(ns advent-of-code-2023.day16
2
2
(:require
3
- [advent-of-code-2023.utils.string :as u ]))
3
+ [advent-of-code-2023.utils.graph :as g ]))
4
4
5
- (defn parse-input [input])
5
+ ; ; For debug purposes
6
+ (defn- assoc-beams [{:keys [positions] :as c} [x y dir]]
7
+ (if (#{\| \- \\ \/} (positions [x y]))
8
+ c
9
+ (assoc-in c [:positions [x y]]
10
+ (condp = dir
11
+ :north \^
12
+ :east \>
13
+ :south \v
14
+ :west \<
15
+ :? ))))
6
16
7
- (defn day16-1 [parsed-input])
17
+ ; ; For debug purposes
18
+ (defn- assoc-energized [c [x y]]
19
+ (assoc-in c [:positions [x y]] \#))
8
20
9
- (defn day16-2 [parsed-input])
21
+ (defn parse-input [input]
22
+ (g/parse-positional-map input identity))
23
+
24
+ (defn- move-beam [[_ _ direction :as position]]
25
+ (condp = direction
26
+ :north (update position 1 dec)
27
+ :east (update position 0 inc)
28
+ :south (update position 1 inc)
29
+ :west (update position 0 dec)))
30
+
31
+ (defn- split-beam [dir val [x y]]
32
+ (condp = [dir val]
33
+ [:east \|] [[x y :north ] [x y :south ]]
34
+ [:west \|] [[x y :north ] [x y :south ]]
35
+ [:north \-] [[x y :east ] [x y :west ]]
36
+ [:south \-] [[x y :east ] [x y :west ]]
37
+ nil ))
38
+
39
+ (defn- trace-beam
40
+ ([contraption start-pos]
41
+ (trace-beam contraption start-pos #{}))
42
+ ([{:keys [positions] :as contraption} beam-position beam-positions]
43
+ (let [[x y dir :as np] (move-beam beam-position)
44
+ val (positions (butlast np))]
45
+ ; ; It is not enough to currently be in the same position and same direction
46
+ ; ; for a cycle. We also need to have come from the same position
47
+ (if (and (beam-positions beam-position) (beam-positions np))
48
+ beam-positions
49
+ (condp = val
50
+ ; ; We are outside of the grid -> stop
51
+ nil (conj beam-positions beam-position)
52
+ \. (recur contraption np (conj beam-positions beam-position))
53
+ \| (if-let [[dir1 dir2] (split-beam dir val np)]
54
+ (let [up-beam-positions
55
+ (trace-beam contraption dir1 (conj beam-positions beam-position))]
56
+ (recur contraption dir2 up-beam-positions))
57
+ ; ; We simply pass through the mirror
58
+ (recur contraption np (conj beam-positions beam-position)))
59
+ \- (if-let [[dir1 dir2] (split-beam dir val np)]
60
+ (let [left-beam-positions
61
+ (trace-beam contraption dir1 (conj beam-positions beam-position))]
62
+ (trace-beam contraption dir2 left-beam-positions))
63
+ ; ; We simply pass through the mirror
64
+ (recur contraption np (conj beam-positions beam-position)))
65
+ \\ (recur contraption [x y (condp = dir
66
+ :north :west
67
+ :south :east
68
+ :east :south
69
+ :west :north )]
70
+ (conj beam-positions beam-position))
71
+ \/ (recur contraption [x y (condp = dir
72
+ :north :east
73
+ :south :west
74
+ :east :north
75
+ :west :south )]
76
+ (conj beam-positions beam-position)))))))
77
+
78
+ (defn- energy [beam-positions]
79
+ ; ; We have to subtract one, because our result also contains the
80
+ ; ; start point otuside of the grid
81
+ (dec (count (set (mapv butlast beam-positions)))))
82
+
83
+ (defn- day16 [contraption beam-start]
84
+ (energy (trace-beam contraption beam-start)))
85
+
86
+ (defn day16-1 [contraption]
87
+ (day16 contraption [-1 0 :east ]))
88
+
89
+ (defn day16-2 [{:keys [height width] :as contraption}]
90
+ (let [beam-starts (concat
91
+ (for [x (range width)] [x -1 :south ])
92
+ (for [x (range width)] [x height :north ])
93
+ (for [y (range height)] [-1 y :east ])
94
+ (for [y (range height)] [width y :west ]))]
95
+ (->> beam-starts
96
+ (pmap (partial day16 contraption))
97
+ (reduce max))))
0 commit comments