+2
-8
2022/day01.livemd
+2
-8
2022/day01.livemd
···
4
4
5
5
```elixir
6
6
Mix.install([
7
-
{:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}
7
+
{:kino_aoc, ">= 0.0.0"}
8
8
])
9
9
```
10
10
11
-
<!-- livebook:{"output":true} -->
12
-
13
-
```
14
-
:ok
15
-
```
16
-
17
11
## Setup
18
12
19
-
<!-- livebook:{"attrs":{"day":"1","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
13
+
<!-- livebook:{"attrs":{"day":"1","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
14
21
15
```elixir
22
16
{:ok, puzzle_input} =
+1
-1
2022/day06.livemd
+1
-1
2022/day06.livemd
···
16
16
17
17
## Section
18
18
19
-
<!-- livebook:{"attrs":{"day":"6","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"6","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
+1
-1
2022/day07.livemd
+1
-1
2022/day07.livemd
···
16
16
17
17
## Section
18
18
19
-
<!-- livebook:{"attrs":{"day":"7","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"7","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
+1
-1
2022/day08.livemd
+1
-1
2022/day08.livemd
···
16
16
17
17
## Section
18
18
19
-
<!-- livebook:{"attrs":{"day":"8","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"8","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
+1
-1
2022/day09.livemd
+1
-1
2022/day09.livemd
···
16
16
17
17
## Setup
18
18
19
-
<!-- livebook:{"attrs":{"day":"9","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"9","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
+1
-1
2022/day10.livemd
+1
-1
2022/day10.livemd
···
16
16
17
17
## Section
18
18
19
-
<!-- livebook:{"attrs":{"day":"10","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"10","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
+1
-1
2022/day11.livemd
+1
-1
2022/day11.livemd
···
16
16
17
17
## Section
18
18
19
-
<!-- livebook:{"attrs":{"day":"11","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"11","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
+1
-1
2022/day12.livemd
+1
-1
2022/day12.livemd
···
17
17
18
18
## Section
19
19
20
-
<!-- livebook:{"attrs":{"day":"12","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
+
<!-- livebook:{"attrs":{"day":"12","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
21
21
22
22
```elixir
23
23
{:ok, puzzle_input} =
+1
-1
2022/day13.livemd
+1
-1
2022/day13.livemd
···
16
16
17
17
## Section
18
18
19
-
<!-- livebook:{"attrs":{"day":"13","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"13","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
+92
-56
2022/day14.livemd
+92
-56
2022/day14.livemd
···
10
10
],
11
11
consolidate_protocols: false
12
12
)
13
+
14
+
# defimpl Kino.Render, for: Vix.Vips.Image do
15
+
# alias Vix.Vips.Image, as: VImg
16
+
17
+
# def to_livebook(image) do
18
+
# format = "png"
19
+
20
+
# {:ok, image_bin} = VImg.write_to_buffer(image, ".#{format}")
21
+
# Kino.Output.image(image_bin, "image/#{format}")
22
+
# end
23
+
# end
13
24
```
14
25
15
26
<!-- livebook:{"output":true} -->
···
20
31
21
32
## Setup
22
33
23
-
<!-- livebook:{"attrs":{"day":"14","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
34
+
<!-- livebook:{"attrs":{"day":"14","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
24
35
25
36
```elixir
26
37
{:ok, puzzle_input} =
···
36
47
37
48
```elixir
38
49
defmodule Cave do
39
-
defstruct map: MapSet.new(), occupied: MapSet.new(), width: nil, height: 0, start: {500, 0}
50
+
defstruct map: %{}, width: nil, height: 0, start: {500, 0}
40
51
41
52
def parse(input, start \\ {500, 0}) do
42
53
map =
43
54
input
44
55
|> String.split("\n", trim: true)
45
56
|> Enum.map(&Cave.parse_line/1)
46
-
|> Enum.reduce(&MapSet.union/2)
57
+
|> Enum.reduce(&Map.merge/2)
47
58
48
59
{width, height} =
49
-
for {x, y} <- map,
60
+
for {{x, y}, _} <- map,
50
61
reduce: {nil, nil} do
51
62
{nil, nil} ->
52
63
{x..x, y}
···
55
66
{min(min_x, x)..max(max_x, x), max(max_y, y)}
56
67
end
57
68
58
-
%__MODULE__{map: map, occupied: map, start: start, width: width, height: height}
59
-
end
60
-
61
-
def add_line(%__MODULE__{} = cave, line) do
62
-
{width, height} =
63
-
Enum.reduce(line, {cave.width, cave.height}, fn {x, y}, {x0..x1, h} ->
64
-
{min(x, x0)..max(x, x1), max(y, h)}
65
-
end)
66
-
67
-
struct(cave,
68
-
width: width,
69
-
height: height,
70
-
map: MapSet.union(cave.map, line),
71
-
occupied: MapSet.union(cave.occupied, line)
72
-
)
69
+
%__MODULE__{map: map, start: start, width: width, height: height}
73
70
end
74
71
75
72
def parse_point(str) do
···
91
88
[{x1, y}, {x2, y}] ->
92
89
for x <- x1..x2, do: {x, y}
93
90
end)
94
-
|> MapSet.new()
91
+
|> Map.new(&{&1, :rock})
95
92
96
93
points
97
94
end
98
95
99
96
def drop_sand(%__MODULE__{} = cave), do: drop_sand(cave, cave.start)
100
97
101
-
def drop_sand(%__MODULE__{height: h, width: x0..x1} = cave, {sx, sy})
102
-
when sx not in x0..x1 or sy >= h,
103
-
do: {:fall_out, cave}
98
+
def drop_sand(%__MODULE__{height: h} = cave, {_, sy} = p)
99
+
when sy >= h,
100
+
do: {p, struct(cave, map: Map.put(cave.map, p, :sand))}
104
101
105
-
def drop_sand(%__MODULE__{} = cave, {sx, sy}) do
102
+
def drop_sand(%__MODULE__{map: map} = cave, {sx, sy} = p) do
106
103
cond do
107
-
{sx, sy + 1} not in cave.occupied -> drop_sand(cave, {sx, sy + 1})
108
-
{sx - 1, sy + 1} not in cave.occupied -> drop_sand(cave, {sx - 1, sy + 1})
109
-
{sx + 1, sy + 1} not in cave.occupied -> drop_sand(cave, {sx + 1, sy + 1})
110
-
true -> {{sx, sy}, struct(cave, occupied: MapSet.put(cave.occupied, {sx, sy}))}
104
+
not Map.has_key?(map, {sx, sy + 1}) -> drop_sand(cave, {sx, sy + 1})
105
+
not Map.has_key?(map, {sx - 1, sy + 1}) -> drop_sand(cave, {sx - 1, sy + 1})
106
+
not Map.has_key?(map, {sx + 1, sy + 1}) -> drop_sand(cave, {sx + 1, sy + 1})
107
+
true -> {p, struct(cave, map: Map.put(cave.map, p, :sand))}
111
108
end
112
109
end
113
-
end
114
110
115
-
defimpl Kino.Render, for: Cave do
116
-
def to_livebook(%@for{} = cave) do
117
-
x0..x1 = cave.width
111
+
def to_image(%__MODULE__{} = cave) do
112
+
{{{x0, _}, _}, {{x1, _}, _}} = Enum.min_max_by(cave.map, fn {{x, _}, _} -> x end)
118
113
{sx, sy} = cave.start
119
114
image = Image.new!(x1 - x0 + 3, cave.height + 3)
120
115
···
122
117
Image.mutate(image, fn im ->
123
118
Image.Draw.point(im, sx - x0 + 1, sy + 1, color: :red)
124
119
125
-
for {x, y} <- cave.occupied do
126
-
Image.Draw.point(im, x - x0 + 1, y + 1, color: :tan)
127
-
end
128
-
129
-
for {x, y} <- cave.map do
130
-
Image.Draw.point(im, x - x0 + 1, y + 1, color: :white)
131
-
end
120
+
cave.map
121
+
|> Enum.sort()
122
+
|> Enum.each(fn {{x, y}, type} ->
123
+
case type do
124
+
:rock -> Image.Draw.point(im, x - x0 + 1, y + 1, color: :white)
125
+
:sand -> Image.Draw.point(im, x - x0 + 1, y + 1, color: :tan)
126
+
end
127
+
end)
132
128
133
129
:ok
134
130
end)
135
131
136
-
buf =
137
-
image
138
-
|> Image.resize!(4, interpolate: :nearest)
139
-
|> Image.write!(:memory, suffix: ".png")
132
+
image
133
+
end
134
+
end
140
135
141
-
Kino.Output.image(buf, "image/png")
136
+
defimpl Kino.Render, for: Cave do
137
+
def to_livebook(%@for{} = cave) do
138
+
cave
139
+
|> @for.to_image()
140
+
|> Image.resize!(4, interpolate: :nearest)
141
+
|> Kino.Render.to_livebook()
142
142
end
143
143
end
144
144
```
···
146
146
<!-- livebook:{"output":true} -->
147
147
148
148
```
149
-
{:module, Kino.Render.Cave, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:to_livebook, 1}}
149
+
{:module, Kino.Render.Cave, <<70, 79, 82, 49, 0, 0, 9, ...>>, {:to_livebook, 1}}
150
150
```
151
151
152
152
```elixir
153
153
cave = Cave.parse(puzzle_input)
154
+
155
+
floor = cave.height + 1
156
+
157
+
cave = struct(cave, height: floor)
154
158
```
155
159
156
160
## Task 1
157
161
158
162
```elixir
159
-
Stream.unfold(cave, &Cave.drop_sand/1)
160
-
|> Enum.take_while(&(&1 != :fall_out))
161
-
|> length()
163
+
frame = Kino.Frame.new() |> Kino.render()
164
+
165
+
image = Cave.to_image(cave)
166
+
167
+
cave
168
+
|> Stream.unfold(fn cave ->
169
+
{_, new_cave} = ret = Cave.drop_sand(cave)
170
+
171
+
{ret, new_cave}
172
+
end)
173
+
|> Enum.reduce_while(0, fn {{_x, y}, cave}, acc ->
174
+
if y < cave.height do
175
+
{:cont, acc + 1}
176
+
else
177
+
Kino.Frame.render(frame, Image.resize!(Cave.to_image(cave), 4, interpolate: :nearest))
178
+
{:halt, acc}
179
+
end
180
+
end)
162
181
```
163
182
164
183
<!-- livebook:{"output":true} -->
···
170
189
## Task 2
171
190
172
191
```elixir
173
-
floor_y = cave.height + 2
192
+
{grains, pyramid} =
193
+
Stream.unfold(cave, fn cave ->
194
+
{_, new_cave} = ret = Cave.drop_sand(cave)
195
+
196
+
{ret, new_cave}
197
+
end)
198
+
|> Enum.reduce_while(0, fn {p, cave}, acc ->
199
+
if p != {500, 0} do
200
+
{:cont, acc + 1}
201
+
else
202
+
{:halt, {acc + 1, cave}}
203
+
end
204
+
end)
205
+
206
+
grains
207
+
```
174
208
175
-
floor = for x <- 0..(cave.width.last * 2), into: MapSet.new(), do: {x, floor_y}
209
+
<!-- livebook:{"output":true} -->
176
210
177
-
cave = Cave.add_line(cave, floor)
211
+
```
212
+
26686
213
+
```
178
214
179
-
Stream.unfold(cave, &Cave.drop_sand/1)
180
-
|> Enum.take_while(&(&1 != cave.start))
181
-
|> length()
182
-
|> then(&(&1 + 1))
215
+
```elixir
216
+
Kino.render(pyramid)
217
+
218
+
:ok
183
219
```
184
220
185
221
<!-- livebook:{"output":true} -->
186
222
187
223
```
188
-
26686
224
+
:ok
189
225
```
+25
-5
2022/day15.livemd
+25
-5
2022/day15.livemd
···
16
16
17
17
## Section
18
18
19
-
<!-- livebook:{"attrs":{"day":"15","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
19
+
<!-- livebook:{"attrs":{"day":"15","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
20
21
21
```elixir
22
22
{:ok, puzzle_input} =
···
108
108
a
109
109
end
110
110
111
+
def continuous?(%__MODULE__{ranges: []}), do: true
112
+
def continuous?(%__MODULE__{ranges: [_]}), do: true
113
+
def continuous?(%__MODULE__{ranges: _}), do: false
114
+
115
+
def gaps(%__MODULE__{ranges: []} = set), do: set
116
+
def gaps(%__MODULE__{ranges: [_]}), do: %__MODULE__{ranges: []}
117
+
111
118
def gaps(%__MODULE__{ranges: ranges}) do
112
119
gaps =
113
120
ranges
···
199
206
<!-- livebook:{"output":true} -->
200
207
201
208
```
202
-
{:module, RangeSet, <<70, 79, 82, 49, 0, 0, 37, ...>>, {:squash, 1}}
209
+
{:module, RangeSet, <<70, 79, 82, 49, 0, 0, 39, ...>>, {:squash, 1}}
203
210
```
204
211
205
212
```elixir
···
272
279
273
280
circles
274
281
|> Beacons.covered_at_line(a_y)
282
+
|> IO.inspect()
275
283
|> RangeSet.remove(beacons_at_line)
276
284
|> RangeSet.length()
277
285
```
···
279
287
<!-- livebook:{"output":true} -->
280
288
281
289
```
290
+
%RangeSet{ranges: [-101830..5006266]}
291
+
```
292
+
293
+
<!-- livebook:{"output":true} -->
294
+
295
+
```
282
296
5108096
283
297
```
284
298
···
293
307
|> Enum.find_value(fn y ->
294
308
covered = Beacons.covered_at_line(circles, y)
295
309
296
-
gaps = RangeSet.gaps(covered)
297
-
298
-
if not RangeSet.empty?(gaps) do
310
+
if not RangeSet.continuous?(covered) do
311
+
gaps = RangeSet.gaps(covered)
299
312
{y, RangeSet.to_list(gaps)}
300
313
end
301
314
end)
315
+
|> Kino.render()
302
316
303
317
x * 4_000_000 + y
318
+
```
319
+
320
+
<!-- livebook:{"output":true} -->
321
+
322
+
```
323
+
{2650264, [2638485]}
304
324
```
305
325
306
326
<!-- livebook:{"output":true} -->
+985
2022/day16.livemd
+985
2022/day16.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 16
4
+
5
+
```elixir
6
+
Mix.install([
7
+
{:kino_aoc, git: "https://github.com/ljgago/kino_aoc"},
8
+
{:libgraph, github: "hauleth/libgraph", ref: "perf/bellman-ford-implementation"}
9
+
])
10
+
```
11
+
12
+
<!-- livebook:{"output":true} -->
13
+
14
+
```
15
+
:ok
16
+
```
17
+
18
+
## Setup
19
+
20
+
<!-- livebook:{"attrs":{"day":"16","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
21
+
22
+
```elixir
23
+
{:ok, puzzle_input} =
24
+
KinoAOC.download_puzzle("2022", "16", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
25
+
```
26
+
27
+
<!-- livebook:{"output":true} -->
28
+
29
+
```
30
+
{:ok,
31
+
"Valve QJ has flow rate=11; tunnels lead to valves HB, GL\nValve VZ has flow rate=10; tunnel leads to valve NE\nValve TX has flow rate=19; tunnels lead to valves MG, OQ, HM\nValve ZI has flow rate=5; tunnels lead to valves BY, ON, RU, LF, JR\nValve IH has flow rate=0; tunnels lead to valves YB, QS\nValve QS has flow rate=22; tunnel leads to valve IH\nValve QB has flow rate=0; tunnels lead to valves QX, ES\nValve NX has flow rate=0; tunnels lead to valves UH, OP\nValve PJ has flow rate=0; tunnels lead to valves OC, UH\nValve OR has flow rate=6; tunnels lead to valves QH, BH, HB, JD\nValve OC has flow rate=7; tunnels lead to valves IZ, JR, TA, ZH, PJ\nValve UC has flow rate=0; tunnels lead to valves AA, BY\nValve QX has flow rate=0; tunnels lead to valves AA, QB\nValve IZ has flow rate=0; tunnels lead to valves OC, SX\nValve AG has flow rate=13; tunnels lead to valves NW, GL, SM\nValve ON has flow rate=0; tunnels lead to valves MO, ZI\nValve XT has flow rate=18; tunnels lead to valves QZ, PG\nValve AX has flow rate=0; tunnels lead to valves UH, MO\nValve JD has flow rate=0; tunnels lead to valves OR, SM\nValve HM has flow rate=0; tunnels lead to valves TX, QH\nValve LF has flow rate=0; tunnels lead to valves ZI, UH\nValve QH has flow rate=0; tunnels lead to valves OR, HM\nValve RT has flow rate=21; tunnel leads to valve PG\nValve NE has flow rate=0; tunnels lead to valves VZ, TA\nValve OQ has flow rate=0; tunnels lead to valves TX, GE\nValve AA has flow rate=0; tunnels lead to valves QZ, UC, OP, QX, EH\nValve UH has flow rate=17; tunnels lead to valves PJ, NX, AX, LF\nValve GE has flow rate=0; tunnels lead to valves YB, OQ\nValve EH has flow rate=0; tunnels lead to valves AA, MO\nValve MG has flow rate=0; tunnels lead to valves TX, NW\nValve YB has flow rate=20; tunnels lead to valves IH, GE, XG\nValve MO has flow rate=15; tunnels lead to valves EH, ON, AX, ZH, CB\nValve JR has flow rate=0; tunnels lead to valves ZI, OC\nValve GL has flow rate=0; tunnels lead to valves AG, QJ\nValve SM has flow rate=0; tunnels lead to valves JD, AG\nValve HB has flow rate=0; tunnels lead to valves OR, QJ\nValve TA has flow rate=0; tunnels lead to valves OC, NE\nValve PG has flow rate=0; tunnels lead to valves RT, XT\nValve XG has flow rate=0; tunnels lead to valves CB, YB\nValve ES has flow rate=9; tunnels lead to valves QB, FL\nValve BH has flow rate=0; tunnels lead to valves RU, OR\nValve FL has flow rate=0; tunnels lead to valves SX, ES\nValve CB has flow rate=0; tunnels lead to valves MO, XG\nValve QZ has flow rate=0; tunnels lead to valves AA, XT\nValve BY has flow rate=0; tunnels lead to valves UC, ZI\nValve ZH has flow rate=0; tunnels lead to valves MO, OC\nValve OP has flow rate=0; tunnels lead to valves NX, AA\nValve NW has flow rate=0; tunnels lead to valves MG, AG\nValve RU has flow rate=0; tunnels lead to valves ZI, BH\nValve SX has flow rate=16; tunnels lead to valves IZ, FL"}
32
+
```
33
+
34
+
```elixir
35
+
# puzzle_input = """
36
+
# Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
37
+
# Valve BB has flow rate=13; tunnels lead to valves CC, AA
38
+
# Valve CC has flow rate=2; tunnels lead to valves DD, BB
39
+
# Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
40
+
# Valve EE has flow rate=3; tunnels lead to valves FF, DD
41
+
# Valve FF has flow rate=0; tunnels lead to valves EE, GG
42
+
# Valve GG has flow rate=0; tunnels lead to valves FF, HH
43
+
# Valve HH has flow rate=22; tunnel leads to valve GG
44
+
# Valve II has flow rate=0; tunnels lead to valves AA, JJ
45
+
# Valve JJ has flow rate=21; tunnel leads to valve II
46
+
# """
47
+
```
48
+
49
+
<!-- livebook:{"output":true} -->
50
+
51
+
```
52
+
nil
53
+
```
54
+
55
+
```elixir
56
+
{{start, _}, valves} =
57
+
valves =
58
+
puzzle_input
59
+
|> String.split("\n", trim: true)
60
+
|> Kino.render()
61
+
|> Enum.map(fn line ->
62
+
%{
63
+
"name" => name,
64
+
"rate" => rate,
65
+
"routes" => routes
66
+
} =
67
+
Regex.named_captures(
68
+
~r/Valve (?<name>..).*rate=(?<rate>\d+);.*valves? (?<routes>.*)$/,
69
+
line
70
+
)
71
+
72
+
{name, %{rate: String.to_integer(rate), routes: String.split(routes, ~r/,\s*/, trim: true)}}
73
+
end)
74
+
|> then(&{hd(&1), Map.new(&1)})
75
+
```
76
+
77
+
<!-- livebook:{"output":true} -->
78
+
79
+
```
80
+
["Valve QJ has flow rate=11; tunnels lead to valves HB, GL",
81
+
"Valve VZ has flow rate=10; tunnel leads to valve NE",
82
+
"Valve TX has flow rate=19; tunnels lead to valves MG, OQ, HM",
83
+
"Valve ZI has flow rate=5; tunnels lead to valves BY, ON, RU, LF, JR",
84
+
"Valve IH has flow rate=0; tunnels lead to valves YB, QS",
85
+
"Valve QS has flow rate=22; tunnel leads to valve IH",
86
+
"Valve QB has flow rate=0; tunnels lead to valves QX, ES",
87
+
"Valve NX has flow rate=0; tunnels lead to valves UH, OP",
88
+
"Valve PJ has flow rate=0; tunnels lead to valves OC, UH",
89
+
"Valve OR has flow rate=6; tunnels lead to valves QH, BH, HB, JD",
90
+
"Valve OC has flow rate=7; tunnels lead to valves IZ, JR, TA, ZH, PJ",
91
+
"Valve UC has flow rate=0; tunnels lead to valves AA, BY",
92
+
"Valve QX has flow rate=0; tunnels lead to valves AA, QB",
93
+
"Valve IZ has flow rate=0; tunnels lead to valves OC, SX",
94
+
"Valve AG has flow rate=13; tunnels lead to valves NW, GL, SM",
95
+
"Valve ON has flow rate=0; tunnels lead to valves MO, ZI",
96
+
"Valve XT has flow rate=18; tunnels lead to valves QZ, PG",
97
+
"Valve AX has flow rate=0; tunnels lead to valves UH, MO",
98
+
"Valve JD has flow rate=0; tunnels lead to valves OR, SM",
99
+
"Valve HM has flow rate=0; tunnels lead to valves TX, QH",
100
+
"Valve LF has flow rate=0; tunnels lead to valves ZI, UH",
101
+
"Valve QH has flow rate=0; tunnels lead to valves OR, HM",
102
+
"Valve RT has flow rate=21; tunnel leads to valve PG",
103
+
"Valve NE has flow rate=0; tunnels lead to valves VZ, TA",
104
+
"Valve OQ has flow rate=0; tunnels lead to valves TX, GE",
105
+
"Valve AA has flow rate=0; tunnels lead to valves QZ, UC, OP, QX, EH",
106
+
"Valve UH has flow rate=17; tunnels lead to valves PJ, NX, AX, LF",
107
+
"Valve GE has flow rate=0; tunnels lead to valves YB, OQ",
108
+
"Valve EH has flow rate=0; tunnels lead to valves AA, MO",
109
+
"Valve MG has flow rate=0; tunnels lead to valves TX, NW",
110
+
"Valve YB has flow rate=20; tunnels lead to valves IH, GE, XG",
111
+
"Valve MO has flow rate=15; tunnels lead to valves EH, ON, AX, ZH, CB",
112
+
"Valve JR has flow rate=0; tunnels lead to valves ZI, OC",
113
+
"Valve GL has flow rate=0; tunnels lead to valves AG, QJ",
114
+
"Valve SM has flow rate=0; tunnels lead to valves JD, AG",
115
+
"Valve HB has flow rate=0; tunnels lead to valves OR, QJ",
116
+
"Valve TA has flow rate=0; tunnels lead to valves OC, NE",
117
+
"Valve PG has flow rate=0; tunnels lead to valves RT, XT",
118
+
"Valve XG has flow rate=0; tunnels lead to valves CB, YB",
119
+
"Valve ES has flow rate=9; tunnels lead to valves QB, FL",
120
+
"Valve BH has flow rate=0; tunnels lead to valves RU, OR",
121
+
"Valve FL has flow rate=0; tunnels lead to valves SX, ES",
122
+
"Valve CB has flow rate=0; tunnels lead to valves MO, XG",
123
+
"Valve QZ has flow rate=0; tunnels lead to valves AA, XT",
124
+
"Valve BY has flow rate=0; tunnels lead to valves UC, ZI",
125
+
"Valve ZH has flow rate=0; tunnels lead to valves MO, OC",
126
+
"Valve OP has flow rate=0; tunnels lead to valves NX, AA",
127
+
"Valve NW has flow rate=0; tunnels lead to valves MG, AG",
128
+
"Valve RU has flow rate=0; tunnels lead to valves ZI, BH",
129
+
"Valve SX has flow rate=16; tunnels lead to valves IZ, FL"]
130
+
```
131
+
132
+
<!-- livebook:{"output":true} -->
133
+
134
+
```
135
+
{{"QJ", %{rate: 11, routes: ["HB", "GL"]}},
136
+
%{
137
+
"CB" => %{rate: 0, routes: ["MO", "XG"]},
138
+
"EH" => %{rate: 0, routes: ["AA", "MO"]},
139
+
"YB" => %{rate: 20, routes: ["IH", "GE", "XG"]},
140
+
"ON" => %{rate: 0, routes: ["MO", "ZI"]},
141
+
"ES" => %{rate: 9, routes: ["QB", "FL"]},
142
+
"XG" => %{rate: 0, routes: ["CB", "YB"]},
143
+
"TX" => %{rate: 19, routes: ["MG", "OQ", "HM"]},
144
+
"RT" => %{rate: 21, routes: ["PG"]},
145
+
"GL" => %{rate: 0, routes: ["AG", "QJ"]},
146
+
"XT" => %{rate: 18, routes: ["QZ", "PG"]},
147
+
"BY" => %{rate: 0, routes: ["UC", "ZI"]},
148
+
"QJ" => %{rate: 11, routes: ["HB", "GL"]},
149
+
"QB" => %{rate: 0, routes: ["QX", "ES"]},
150
+
"QH" => %{rate: 0, routes: ["OR", "HM"]},
151
+
"SX" => %{rate: 16, routes: ["IZ", "FL"]},
152
+
"ZI" => %{rate: 5, routes: ["BY", "ON", "RU", "LF", "JR"]},
153
+
"OC" => %{rate: 7, routes: ["IZ", "JR", "TA", "ZH", "PJ"]},
154
+
"NW" => %{rate: 0, routes: ["MG", "AG"]},
155
+
"UH" => %{rate: 17, routes: ["PJ", "NX", "AX", "LF"]},
156
+
"VZ" => %{rate: 10, routes: ["NE"]},
157
+
"MO" => %{rate: 15, routes: ["EH", "ON", "AX", "ZH", "CB"]},
158
+
"ZH" => %{rate: 0, routes: ["MO", "OC"]},
159
+
"RU" => %{rate: 0, routes: ["ZI", "BH"]},
160
+
"FL" => %{rate: 0, routes: ["SX", "ES"]},
161
+
"SM" => %{rate: 0, routes: ["JD", "AG"]},
162
+
"AA" => %{rate: 0, routes: ["QZ", "UC", "OP", "QX", "EH"]},
163
+
"JR" => %{rate: 0, routes: ["ZI", "OC"]},
164
+
"QS" => %{rate: 22, routes: ["IH"]},
165
+
"AG" => %{rate: 13, routes: ["NW", "GL", "SM"]},
166
+
"JD" => %{rate: 0, routes: ["OR", "SM"]},
167
+
"QZ" => %{rate: 0, routes: ["AA", "XT"]},
168
+
"MG" => %{rate: 0, routes: ["TX", "NW"]},
169
+
"UC" => %{rate: 0, routes: ["AA", "BY"]},
170
+
"AX" => %{rate: 0, routes: ["UH", "MO"]},
171
+
"HM" => %{rate: 0, routes: ["TX", "QH"]},
172
+
"LF" => %{rate: 0, routes: ["ZI", "UH"]},
173
+
"BH" => %{rate: 0, routes: ["RU", "OR"]},
174
+
"OR" => %{rate: 6, routes: ["QH", "BH", "HB", "JD"]},
175
+
"GE" => %{rate: 0, routes: ["YB", "OQ"]},
176
+
"QX" => %{rate: 0, routes: ["AA", "QB"]},
177
+
"IZ" => %{rate: 0, routes: ["OC", "SX"]},
178
+
"PG" => %{rate: 0, routes: ["RT", "XT"]},
179
+
"NX" => %{rate: 0, routes: ["UH", "OP"]},
180
+
"OP" => %{rate: 0, routes: ["NX", "AA"]},
181
+
"TA" => %{rate: 0, routes: ["OC", ...]},
182
+
"IH" => %{rate: 0, routes: [...]},
183
+
"HB" => %{rate: 0, ...},
184
+
"PJ" => %{...},
185
+
...
186
+
}}
187
+
```
188
+
189
+
```elixir
190
+
graph = Graph.new(type: :directed)
191
+
192
+
edges =
193
+
Enum.flat_map(valves, fn {a, %{routes: routes}} ->
194
+
for b <- routes, p <- [{a, b, weight: 1}, {b, a, weight: 1}], do: p
195
+
end)
196
+
197
+
graph =
198
+
Graph.add_edges(graph, edges)
199
+
|> Kino.render()
200
+
201
+
paths =
202
+
for v <- Graph.vertices(graph), into: %{} do
203
+
routes =
204
+
graph
205
+
|> Graph.bellman_ford(v)
206
+
|> Enum.filter(fn {k, _} -> valves[k].rate > 0 and k != v end)
207
+
|> Map.new()
208
+
209
+
{v, routes}
210
+
end
211
+
```
212
+
213
+
<!-- livebook:{"output":true} -->
214
+
215
+
```
216
+
#Graph<type: directed, vertices: ["LF", "CB", "AX", "ZI", "ZH", "VZ", "AA", "UH", "OC", "IH", "FL",
217
+
"JR", "QB", "EH", "QH", "ON", "TA", "PJ", "SX", "YB", "UC", "BH", "MO", "OQ", "HM", "JD", "OR",
218
+
"NE", "QS", "XT", "IZ", "QZ", "BY", "PG", "NW", "HB", "AG", "QJ", "RT", "TX", "GE", "QX", "XG",
219
+
"NX", "GL", "RU", "SM", "ES", "MG",
220
+
"OP"], edges: ["LF" -> "UH", "LF" -> "ZI", "CB" -> "MO", "CB" -> "XG", "AX" -> "UH", "AX" -> "MO", "ZI" -> "BY", "ZI" -> "RU", "ZI" -> "ON", "ZI" -> "LF", "ZI" -> "JR", "ZH" -> "OC", "ZH" -> "MO", "VZ" -> "NE", "AA" -> "UC", "AA" -> "EH", "AA" -> "QX", "AA" -> "OP", "AA" -> "QZ", "UH" -> "LF", "UH" -> "PJ", "UH" -> "AX", "UH" -> "NX", "OC" -> "ZH", "OC" -> "IZ", "OC" -> "TA", "OC" -> "PJ", "OC" -> "JR", "IH" -> "YB", "IH" -> "QS", "FL" -> "SX", "FL" -> "ES", "JR" -> "OC", "JR" -> "ZI", "QB" -> "QX", "QB" -> "ES", "EH" -> "MO", "EH" -> "AA", "QH" -> "OR", "QH" -> "HM", "ON" -> "MO", "ON" -> "ZI", "TA" -> "OC", "TA" -> "NE", "PJ" -> "OC", "PJ" -> "UH", "SX" -> "IZ", "SX" -> "FL", "YB" -> "GE", "YB" -> "IH", "YB" -> "XG", "UC" -> "BY", "UC" -> "AA", "BH" -> "OR", "BH" -> "RU", "MO" -> "ZH", "MO" -> "EH", "MO" -> "ON", "MO" -> "CB", "MO" -> "AX", "OQ" -> "GE", "OQ" -> "TX", "HM" -> "TX", "HM" -> "QH", "JD" -> "OR", "JD" -> "SM", "OR" -> "BH", "OR" -> "HB", "OR" -> "JD", "OR" -> "QH", "NE" -> "TA", "NE" -> "VZ", "QS" -> "IH", "XT" -> "QZ", "XT" -> "PG", "IZ" -> "OC", "IZ" -> "SX", "QZ" -> "AA", "QZ" -> "XT", "BY" -> "UC", "BY" -> "ZI", "PG" -> "RT", "PG" -> "XT", "NW" -> "MG", "NW" -> "AG", "HB" -> "OR", "HB" -> "QJ", "AG" -> "SM", "AG" -> "GL", "AG" -> "NW", "QJ" -> "GL", "QJ" -> "HB", "RT" -> "PG", "TX" -> "OQ", "TX" -> "MG", "TX" -> "HM", "GE" -> "OQ", "GE" -> "YB", "QX" -> "QB", "QX" -> "AA", "XG" -> "YB", "XG" -> "CB", "NX" -> "UH", "NX" -> "OP", "GL" -> "QJ", "GL" -> "AG", "RU" -> "BH", "RU" -> "ZI", "SM" -> "AG", "SM" -> "JD", "ES" -> "QB", "ES" -> "FL", "MG" -> "NW", "MG" -> "TX", "OP" -> "AA", "OP" -> "NX"]>
221
+
```
222
+
223
+
<!-- livebook:{"output":true} -->
224
+
225
+
```
226
+
%{
227
+
"CB" => %{
228
+
"AG" => 8,
229
+
"ES" => 6,
230
+
"MO" => 1,
231
+
"OC" => 3,
232
+
"OR" => 6,
233
+
"QJ" => 8,
234
+
"QS" => 4,
235
+
"RT" => 7,
236
+
"SX" => 5,
237
+
"TX" => 5,
238
+
"UH" => 3,
239
+
"VZ" => 6,
240
+
"XT" => 5,
241
+
"YB" => 2,
242
+
"ZI" => 3
243
+
},
244
+
"EH" => %{
245
+
"AG" => 9,
246
+
"ES" => 4,
247
+
"MO" => 1,
248
+
"OC" => 3,
249
+
"OR" => 6,
250
+
"QJ" => 8,
251
+
"QS" => 6,
252
+
"RT" => 5,
253
+
"SX" => 5,
254
+
"TX" => 7,
255
+
"UH" => 3,
256
+
"VZ" => 6,
257
+
"XT" => 3,
258
+
"YB" => 4,
259
+
"ZI" => 3
260
+
},
261
+
"YB" => %{
262
+
"AG" => 6,
263
+
"ES" => 8,
264
+
"MO" => 3,
265
+
"OC" => 5,
266
+
"OR" => 6,
267
+
"QJ" => 8,
268
+
"QS" => 2,
269
+
"RT" => 9,
270
+
"SX" => 7,
271
+
"TX" => 3,
272
+
"UH" => 5,
273
+
"VZ" => 8,
274
+
"XT" => 7,
275
+
"ZI" => 5
276
+
},
277
+
"ON" => %{
278
+
"AG" => 7,
279
+
"ES" => 6,
280
+
"MO" => 1,
281
+
"OC" => 3,
282
+
"OR" => 4,
283
+
"QJ" => 6,
284
+
"QS" => 6,
285
+
"RT" => 7,
286
+
"SX" => 5,
287
+
"TX" => 7,
288
+
"UH" => 3,
289
+
"VZ" => 6,
290
+
"XT" => 5,
291
+
"YB" => 4,
292
+
"ZI" => 1
293
+
},
294
+
"ES" => %{
295
+
"AG" => 12,
296
+
"MO" => 5,
297
+
"OC" => 4,
298
+
"OR" => 9,
299
+
"QJ" => 11,
300
+
"QS" => 10,
301
+
"RT" => 7,
302
+
"SX" => 2,
303
+
"TX" => 11,
304
+
"UH" => 6,
305
+
"VZ" => 7,
306
+
"XT" => 5,
307
+
"YB" => 8,
308
+
"ZI" => 6
309
+
},
310
+
"XG" => %{
311
+
"AG" => 7,
312
+
"ES" => 7,
313
+
"MO" => 2,
314
+
"OC" => 4,
315
+
"OR" => 7,
316
+
"QJ" => 9,
317
+
"QS" => 3,
318
+
"RT" => 8,
319
+
"SX" => 6,
320
+
"TX" => 4,
321
+
"UH" => 4,
322
+
"VZ" => 7,
323
+
"XT" => 6,
324
+
"YB" => 1,
325
+
"ZI" => 4
326
+
},
327
+
"TX" => %{
328
+
"AG" => 3,
329
+
"ES" => 11,
330
+
"MO" => 6,
331
+
"OC" => 8,
332
+
"OR" => 3,
333
+
"QJ" => 5,
334
+
"QS" => 5,
335
+
"RT" => 12,
336
+
"SX" => 10,
337
+
"UH" => 8,
338
+
"VZ" => 11,
339
+
"XT" => 10,
340
+
"YB" => 3,
341
+
"ZI" => 6
342
+
},
343
+
"RT" => %{
344
+
"AG" => 13,
345
+
"ES" => 7,
346
+
"MO" => 6,
347
+
"OC" => 8,
348
+
"OR" => 10,
349
+
"QJ" => 12,
350
+
"QS" => 11,
351
+
"SX" => 9,
352
+
"TX" => 12,
353
+
"UH" => 7,
354
+
"VZ" => 11,
355
+
"XT" => 2,
356
+
"YB" => 9,
357
+
"ZI" => 7
358
+
},
359
+
"GL" => %{
360
+
"AG" => 1,
361
+
"ES" => 12,
362
+
"MO" => 8,
363
+
"OC" => 8,
364
+
"OR" => 3,
365
+
"QJ" => 1,
366
+
"QS" => 9,
367
+
"RT" => 13,
368
+
"SX" => 10,
369
+
"TX" => 4,
370
+
"UH" => 8,
371
+
"VZ" => 11,
372
+
"XT" => 11,
373
+
"YB" => 7,
374
+
"ZI" => 6
375
+
},
376
+
"XT" => %{
377
+
"AG" => 11,
378
+
"ES" => 5,
379
+
"MO" => 4,
380
+
"OC" => 6,
381
+
"OR" => 8,
382
+
"QJ" => 10,
383
+
"QS" => 9,
384
+
"RT" => 2,
385
+
"SX" => 7,
386
+
"TX" => 10,
387
+
"UH" => 5,
388
+
"VZ" => 9,
389
+
"YB" => 7,
390
+
"ZI" => 5
391
+
},
392
+
"BY" => %{
393
+
"AG" => 7,
394
+
"ES" => 5,
395
+
"MO" => 3,
396
+
"OC" => 3,
397
+
"OR" => 4,
398
+
"QJ" => 6,
399
+
"QS" => 8,
400
+
"RT" => 6,
401
+
"SX" => 5,
402
+
"TX" => 7,
403
+
"UH" => 3,
404
+
"VZ" => 6,
405
+
"XT" => 4,
406
+
"YB" => 6,
407
+
"ZI" => 1
408
+
},
409
+
"QJ" => %{
410
+
"AG" => 2,
411
+
"ES" => 11,
412
+
"MO" => 7,
413
+
"OC" => 7,
414
+
"OR" => 2,
415
+
"QS" => 10,
416
+
"RT" => 12,
417
+
"SX" => 9,
418
+
"TX" => 5,
419
+
"UH" => 7,
420
+
"VZ" => 10,
421
+
"XT" => 10,
422
+
"YB" => 8,
423
+
"ZI" => 5
424
+
},
425
+
"QB" => %{
426
+
"AG" => 11,
427
+
"ES" => 1,
428
+
"MO" => 4,
429
+
"OC" => 5,
430
+
"OR" => 8,
431
+
"QJ" => 10,
432
+
"QS" => 9,
433
+
"RT" => 6,
434
+
"SX" => 3,
435
+
"TX" => 10,
436
+
"UH" => 5,
437
+
"VZ" => 8,
438
+
"XT" => 4,
439
+
"YB" => 7,
440
+
"ZI" => 5
441
+
},
442
+
"QH" => %{
443
+
"AG" => 4,
444
+
"ES" => 10,
445
+
"MO" => 6,
446
+
"OC" => 6,
447
+
"OR" => 1,
448
+
"QJ" => 3,
449
+
"QS" => 7,
450
+
"RT" => 11,
451
+
"SX" => 8,
452
+
"TX" => 2,
453
+
"UH" => 6,
454
+
"VZ" => 9,
455
+
"XT" => 9,
456
+
"YB" => 5,
457
+
"ZI" => 4
458
+
},
459
+
"SX" => %{
460
+
"AG" => 10,
461
+
"ES" => 2,
462
+
"MO" => 4,
463
+
"OC" => 2,
464
+
"OR" => 7,
465
+
"QJ" => 9,
466
+
"QS" => 9,
467
+
"RT" => 9,
468
+
"TX" => 10,
469
+
"UH" => 4,
470
+
"VZ" => 5,
471
+
"XT" => 7,
472
+
"YB" => 7,
473
+
"ZI" => 4
474
+
},
475
+
"ZI" => %{
476
+
"AG" => 6,
477
+
"ES" => 6,
478
+
"MO" => 2,
479
+
"OC" => 2,
480
+
"OR" => 3,
481
+
"QJ" => 5,
482
+
"QS" => 7,
483
+
"RT" => 7,
484
+
"SX" => 4,
485
+
"TX" => 6,
486
+
"UH" => 2,
487
+
"VZ" => 5,
488
+
"XT" => 5,
489
+
"YB" => 5
490
+
},
491
+
"OC" => %{
492
+
"AG" => 8,
493
+
"ES" => 4,
494
+
"MO" => 2,
495
+
"OR" => 5,
496
+
"QJ" => 7,
497
+
"QS" => 7,
498
+
"RT" => 8,
499
+
"SX" => 2,
500
+
"TX" => 8,
501
+
"UH" => 2,
502
+
"VZ" => 3,
503
+
"XT" => 6,
504
+
"YB" => 5,
505
+
"ZI" => 2
506
+
},
507
+
"NW" => %{
508
+
"AG" => 1,
509
+
"ES" => 13,
510
+
"MO" => 8,
511
+
"OC" => 9,
512
+
"OR" => 4,
513
+
"QJ" => 3,
514
+
"QS" => 7,
515
+
"RT" => 14,
516
+
"SX" => 11,
517
+
"TX" => 2,
518
+
"UH" => 9,
519
+
"VZ" => 12,
520
+
"XT" => 12,
521
+
"YB" => 5,
522
+
"ZI" => 7
523
+
},
524
+
"UH" => %{
525
+
"AG" => 8,
526
+
"ES" => 6,
527
+
"MO" => 2,
528
+
"OC" => 2,
529
+
"OR" => 5,
530
+
"QJ" => 7,
531
+
"QS" => 7,
532
+
"RT" => 7,
533
+
"SX" => 4,
534
+
"TX" => 8,
535
+
"VZ" => 5,
536
+
"XT" => 5,
537
+
"YB" => 5,
538
+
"ZI" => 2
539
+
},
540
+
"VZ" => %{
541
+
"AG" => 11,
542
+
"ES" => 7,
543
+
"MO" => 5,
544
+
"OC" => 3,
545
+
"OR" => 8,
546
+
"QJ" => 10,
547
+
"QS" => 10,
548
+
"RT" => 11,
549
+
"SX" => 5,
550
+
"TX" => 11,
551
+
"UH" => 5,
552
+
"XT" => 9,
553
+
"YB" => 8,
554
+
"ZI" => 5
555
+
},
556
+
"MO" => %{
557
+
"AG" => 8,
558
+
"ES" => 5,
559
+
"OC" => 2,
560
+
"OR" => 5,
561
+
"QJ" => 7,
562
+
"QS" => 5,
563
+
"RT" => 6,
564
+
"SX" => 4,
565
+
"TX" => 6,
566
+
"UH" => 2,
567
+
"VZ" => 5,
568
+
"XT" => 4,
569
+
"YB" => 3,
570
+
"ZI" => 2
571
+
},
572
+
"ZH" => %{
573
+
"AG" => 9,
574
+
"ES" => 5,
575
+
"MO" => 1,
576
+
"OC" => 1,
577
+
"OR" => 6,
578
+
"QJ" => 8,
579
+
"QS" => 6,
580
+
"RT" => 7,
581
+
"SX" => 3,
582
+
"TX" => 7,
583
+
"UH" => 3,
584
+
"VZ" => 4,
585
+
"XT" => 5,
586
+
"YB" => 4,
587
+
"ZI" => 3
588
+
},
589
+
"RU" => %{
590
+
"AG" => 5,
591
+
"ES" => 7,
592
+
"MO" => 3,
593
+
"OC" => 3,
594
+
"OR" => 2,
595
+
"QJ" => 4,
596
+
"QS" => 8,
597
+
"RT" => 8,
598
+
"SX" => 5,
599
+
"TX" => 5,
600
+
"UH" => 3,
601
+
"VZ" => 6,
602
+
"XT" => 6,
603
+
"YB" => 6,
604
+
"ZI" => 1
605
+
},
606
+
"FL" => %{
607
+
"AG" => 11,
608
+
"ES" => 1,
609
+
"MO" => 5,
610
+
"OC" => 3,
611
+
"OR" => 8,
612
+
"QJ" => 10,
613
+
"QS" => 10,
614
+
"RT" => 8,
615
+
"SX" => 1,
616
+
"TX" => 11,
617
+
"UH" => 5,
618
+
"VZ" => 6,
619
+
"XT" => 6,
620
+
"YB" => 8,
621
+
"ZI" => 5
622
+
},
623
+
"SM" => %{
624
+
"AG" => 1,
625
+
"ES" => 11,
626
+
"MO" => 7,
627
+
"OC" => 7,
628
+
"OR" => 2,
629
+
"QJ" => 3,
630
+
"QS" => 9,
631
+
"RT" => 12,
632
+
"SX" => 9,
633
+
"TX" => 4,
634
+
"UH" => 7,
635
+
"VZ" => 10,
636
+
"XT" => 10,
637
+
"YB" => 7,
638
+
"ZI" => 5
639
+
},
640
+
"AA" => %{
641
+
"AG" => 9,
642
+
"ES" => 3,
643
+
"MO" => 2,
644
+
"OC" => 4,
645
+
"OR" => 6,
646
+
"QJ" => 8,
647
+
"QS" => 7,
648
+
"RT" => 4,
649
+
"SX" => 5,
650
+
"TX" => 8,
651
+
"UH" => 3,
652
+
"VZ" => 7,
653
+
"XT" => 2,
654
+
"YB" => 5,
655
+
"ZI" => 3
656
+
},
657
+
"JR" => %{
658
+
"AG" => 7,
659
+
"ES" => 5,
660
+
"MO" => 3,
661
+
"OC" => 1,
662
+
"OR" => 4,
663
+
"QJ" => 6,
664
+
"QS" => 8,
665
+
"RT" => 8,
666
+
"SX" => 3,
667
+
"TX" => 7,
668
+
"UH" => 3,
669
+
"VZ" => 4,
670
+
"XT" => 6,
671
+
"YB" => 6,
672
+
"ZI" => 1
673
+
},
674
+
"QS" => %{
675
+
"AG" => 8,
676
+
"ES" => 10,
677
+
"MO" => 5,
678
+
"OC" => 7,
679
+
"OR" => 8,
680
+
"QJ" => 10,
681
+
"RT" => 11,
682
+
"SX" => 9,
683
+
"TX" => 5,
684
+
"UH" => 7,
685
+
"VZ" => 10,
686
+
"XT" => 9,
687
+
"YB" => 2,
688
+
"ZI" => 7
689
+
},
690
+
"AG" => %{
691
+
"ES" => 12,
692
+
"MO" => 8,
693
+
"OC" => 8,
694
+
"OR" => 3,
695
+
"QJ" => 2,
696
+
"QS" => 8,
697
+
"RT" => 13,
698
+
"SX" => 10,
699
+
"TX" => 3,
700
+
"UH" => 8,
701
+
"VZ" => 11,
702
+
"XT" => 11,
703
+
"YB" => 6,
704
+
"ZI" => 6
705
+
},
706
+
"JD" => %{
707
+
"AG" => 2,
708
+
"ES" => 10,
709
+
"MO" => 6,
710
+
"OC" => 6,
711
+
"OR" => 1,
712
+
"QJ" => 3,
713
+
"QS" => 9,
714
+
"RT" => 11,
715
+
"SX" => 8,
716
+
"TX" => 4,
717
+
"UH" => 6,
718
+
"VZ" => 9,
719
+
"XT" => 9,
720
+
"YB" => 7,
721
+
"ZI" => 4
722
+
},
723
+
"QZ" => %{
724
+
"AG" => 10,
725
+
"ES" => 4,
726
+
"MO" => 3,
727
+
"OC" => 5,
728
+
"OR" => 7,
729
+
"QJ" => 9,
730
+
"QS" => 8,
731
+
"RT" => 3,
732
+
"SX" => 6,
733
+
"TX" => 9,
734
+
"UH" => 4,
735
+
"VZ" => 8,
736
+
"XT" => 1,
737
+
"YB" => 6,
738
+
"ZI" => 4
739
+
},
740
+
"MG" => %{
741
+
"AG" => 2,
742
+
"ES" => 12,
743
+
"MO" => 7,
744
+
"OC" => 9,
745
+
"OR" => 4,
746
+
"QJ" => 4,
747
+
"QS" => 6,
748
+
"RT" => 13,
749
+
"SX" => 11,
750
+
"TX" => 1,
751
+
"UH" => 9,
752
+
"VZ" => 12,
753
+
"XT" => 11,
754
+
"YB" => 4,
755
+
"ZI" => 7
756
+
},
757
+
"UC" => %{
758
+
"AG" => 8,
759
+
"ES" => 4,
760
+
"MO" => 3,
761
+
"OC" => 4,
762
+
"OR" => 5,
763
+
"QJ" => 7,
764
+
"QS" => 8,
765
+
"RT" => 5,
766
+
"SX" => 6,
767
+
"TX" => 8,
768
+
"UH" => 4,
769
+
"VZ" => 7,
770
+
"XT" => 3,
771
+
"YB" => 6,
772
+
"ZI" => 2
773
+
},
774
+
"AX" => %{
775
+
"AG" => 9,
776
+
"ES" => 6,
777
+
"MO" => 1,
778
+
"OC" => 3,
779
+
"OR" => 6,
780
+
"QJ" => 8,
781
+
"QS" => 6,
782
+
"RT" => 7,
783
+
"SX" => 5,
784
+
"TX" => 7,
785
+
"UH" => 1,
786
+
"VZ" => 6,
787
+
"XT" => 5,
788
+
"YB" => 4,
789
+
"ZI" => 3
790
+
},
791
+
"HM" => %{
792
+
"AG" => 4,
793
+
"ES" => 11,
794
+
"MO" => 7,
795
+
"OC" => 7,
796
+
"OR" => 2,
797
+
"QJ" => 4,
798
+
"QS" => 6,
799
+
"RT" => 12,
800
+
"SX" => 9,
801
+
"TX" => 1,
802
+
"UH" => 7,
803
+
"VZ" => 10,
804
+
"XT" => 10,
805
+
"YB" => 4,
806
+
"ZI" => 5
807
+
},
808
+
"LF" => %{
809
+
"AG" => 7,
810
+
"ES" => 7,
811
+
"MO" => 3,
812
+
"OC" => 3,
813
+
"OR" => 4,
814
+
"QJ" => 6,
815
+
"QS" => 8,
816
+
"RT" => 8,
817
+
"SX" => 5,
818
+
"TX" => 7,
819
+
"UH" => 1,
820
+
"VZ" => 6,
821
+
"XT" => 6,
822
+
"YB" => 6,
823
+
...
824
+
},
825
+
"BH" => %{
826
+
"AG" => 4,
827
+
"ES" => 8,
828
+
"MO" => 4,
829
+
"OC" => 4,
830
+
"OR" => 1,
831
+
"QJ" => 3,
832
+
"QS" => 9,
833
+
"RT" => 9,
834
+
"SX" => 6,
835
+
"TX" => 4,
836
+
"UH" => 4,
837
+
"VZ" => 7,
838
+
"XT" => 7,
839
+
...
840
+
},
841
+
"OR" => %{
842
+
"AG" => 3,
843
+
"ES" => 9,
844
+
"MO" => 5,
845
+
"OC" => 5,
846
+
"QJ" => 2,
847
+
"QS" => 8,
848
+
"RT" => 10,
849
+
"SX" => 7,
850
+
"TX" => 3,
851
+
"UH" => 5,
852
+
"VZ" => 8,
853
+
"XT" => 8,
854
+
...
855
+
},
856
+
"GE" => %{
857
+
"AG" => 5,
858
+
"ES" => 9,
859
+
"MO" => 4,
860
+
"OC" => 6,
861
+
"OR" => 5,
862
+
"QJ" => 7,
863
+
"QS" => 3,
864
+
"RT" => 10,
865
+
"SX" => 8,
866
+
"TX" => 2,
867
+
"UH" => 6,
868
+
...
869
+
},
870
+
"QX" => %{
871
+
"AG" => 10,
872
+
"ES" => 2,
873
+
"MO" => 3,
874
+
"OC" => 5,
875
+
"OR" => 7,
876
+
"QJ" => 9,
877
+
"QS" => 8,
878
+
"RT" => 5,
879
+
"SX" => 4,
880
+
"TX" => 9,
881
+
...
882
+
},
883
+
"IZ" => %{
884
+
"AG" => 9,
885
+
"ES" => 3,
886
+
"MO" => 3,
887
+
"OC" => 1,
888
+
"OR" => 6,
889
+
"QJ" => 8,
890
+
"QS" => 8,
891
+
"RT" => 9,
892
+
"SX" => 1,
893
+
...
894
+
},
895
+
"PG" => %{
896
+
"AG" => 12,
897
+
"ES" => 6,
898
+
"MO" => 5,
899
+
"OC" => 7,
900
+
"OR" => 9,
901
+
"QJ" => 11,
902
+
"QS" => 10,
903
+
"RT" => 1,
904
+
...
905
+
},
906
+
"NX" => %{"AG" => 9, "ES" => 5, "MO" => 3, "OC" => 3, "OR" => 6, "QJ" => 8, "QS" => 8, ...},
907
+
"OP" => %{"AG" => 10, "ES" => 4, "MO" => 3, "OC" => 4, "OR" => 7, "QJ" => 9, ...},
908
+
"TA" => %{"AG" => 9, "ES" => 5, "MO" => 3, "OC" => 1, "OR" => 6, ...},
909
+
"IH" => %{"AG" => 7, "ES" => 9, "MO" => 4, "OC" => 6, ...},
910
+
"HB" => %{"AG" => 3, "ES" => 10, "MO" => 6, ...},
911
+
"PJ" => %{"AG" => 9, "ES" => 5, ...},
912
+
"OQ" => %{"AG" => 4, ...},
913
+
"NE" => %{...}
914
+
}
915
+
```
916
+
917
+
## Task 1
918
+
919
+
```elixir
920
+
defmodule Alone do
921
+
def visit(current, valves, paths, left, opened) when left >= 0 do
922
+
{left, rate, opened} =
923
+
case valves[current].rate do
924
+
0 -> {left, 0, opened}
925
+
other -> {left - 1, other, Map.put(opened, current, left - 1)}
926
+
end
927
+
928
+
rate = rate * left
929
+
930
+
paths[current]
931
+
|> Enum.map(fn
932
+
{next, weight} when weight + 1 < left and not is_map_key(opened, next) ->
933
+
{val, opened} = visit(next, valves, paths, left - weight, opened)
934
+
{val + rate, opened}
935
+
936
+
_ ->
937
+
{rate, opened}
938
+
end)
939
+
|> Enum.max_by(&elem(&1, 0))
940
+
end
941
+
end
942
+
```
943
+
944
+
<!-- livebook:{"output":true} -->
945
+
946
+
```
947
+
{:module, Valves, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:visit, 5}}
948
+
```
949
+
950
+
```elixir
951
+
{t, v} = Alone.visit("AA", valves, paths, 30, %{})
952
+
```
953
+
954
+
<!-- livebook:{"output":true} -->
955
+
956
+
```
957
+
{1820, %{"AG" => 6, "MO" => 23, "QJ" => 3, "QS" => 16, "TX" => 10, "UH" => 26, "YB" => 19}}
958
+
```
959
+
960
+
## Task 2
961
+
962
+
```elixir
963
+
defmodule Alone do
964
+
def visit(current, valves, paths, left, opened) when left >= 0 do
965
+
{left, rate, opened} =
966
+
case valves[current].rate do
967
+
0 -> {left, 0, opened}
968
+
other -> {left - 1, other, Map.put(opened, current, left - 1)}
969
+
end
970
+
971
+
rate = rate * left
972
+
973
+
paths[current]
974
+
|> Enum.map(fn
975
+
{next, weight} when weight + 1 < left and not is_map_key(opened, next) ->
976
+
{val, opened} = visit(next, valves, paths, left - weight, opened)
977
+
{val + rate, opened}
978
+
979
+
_ ->
980
+
{rate, opened}
981
+
end)
982
+
|> Enum.max_by(&elem(&1, 0))
983
+
end
984
+
end
985
+
```
+188
2022/day17.livemd
+188
2022/day17.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 17
4
+
5
+
```elixir
6
+
Mix.install([
7
+
{:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}
8
+
])
9
+
```
10
+
11
+
<!-- livebook:{"output":true} -->
12
+
13
+
```
14
+
* Getting kino_aoc (https://github.com/ljgago/kino_aoc)
15
+
remote: Enumerating objects: 103, done.
16
+
remote: Counting objects: 100% (103/103), done.
17
+
remote: Compressing objects: 100% (68/68), done.
18
+
remote: Total 103 (delta 40), reused 84 (delta 25), pack-reused 0
19
+
origin/HEAD set to main
20
+
Resolving Hex dependencies...
21
+
Resolution completed in 0.336s
22
+
New:
23
+
castore 1.0.3
24
+
finch 0.16.0
25
+
hpax 0.1.2
26
+
jason 1.4.1
27
+
kino 0.10.0
28
+
mime 2.0.5
29
+
mint 1.5.1
30
+
nimble_options 1.0.2
31
+
nimble_pool 1.0.0
32
+
req 0.3.10
33
+
table 0.1.2
34
+
telemetry 1.2.1
35
+
* Getting kino (Hex package)
36
+
* Getting req (Hex package)
37
+
* Getting finch (Hex package)
38
+
* Getting jason (Hex package)
39
+
* Getting mime (Hex package)
40
+
* Getting castore (Hex package)
41
+
* Getting mint (Hex package)
42
+
* Getting nimble_options (Hex package)
43
+
* Getting nimble_pool (Hex package)
44
+
* Getting telemetry (Hex package)
45
+
* Getting hpax (Hex package)
46
+
* Getting table (Hex package)
47
+
==> table
48
+
Compiling 5 files (.ex)
49
+
Generated table app
50
+
==> mime
51
+
Compiling 1 file (.ex)
52
+
Generated mime app
53
+
==> nimble_options
54
+
Compiling 3 files (.ex)
55
+
Generated nimble_options app
56
+
==> kino
57
+
Compiling 41 files (.ex)
58
+
Generated kino app
59
+
===> Analyzing applications...
60
+
===> Compiling telemetry
61
+
==> jason
62
+
Compiling 10 files (.ex)
63
+
Generated jason app
64
+
==> hpax
65
+
Compiling 4 files (.ex)
66
+
Generated hpax app
67
+
==> nimble_pool
68
+
Compiling 2 files (.ex)
69
+
Generated nimble_pool app
70
+
==> castore
71
+
Compiling 1 file (.ex)
72
+
Generated castore app
73
+
==> mint
74
+
Compiling 1 file (.erl)
75
+
Compiling 19 files (.ex)
76
+
Generated mint app
77
+
==> finch
78
+
Compiling 13 files (.ex)
79
+
Generated finch app
80
+
==> req
81
+
Compiling 5 files (.ex)
82
+
Generated req app
83
+
==> kino_aoc
84
+
Compiling 3 files (.ex)
85
+
Generated kino_aoc app
86
+
```
87
+
88
+
<!-- livebook:{"output":true} -->
89
+
90
+
```
91
+
:ok
92
+
```
93
+
94
+
## Section
95
+
96
+
<!-- livebook:{"attrs":{"day":"17","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
97
+
98
+
```elixir
99
+
{:ok, puzzle_input} =
100
+
KinoAOC.download_puzzle("2022", "17", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
101
+
```
102
+
103
+
<!-- livebook:{"output":true} -->
104
+
105
+
```
106
+
{:ok,
107
+
">><<<>><<<<>>><>><>>><<<>>>><>>><<><<<>>>><<<><<<><<><<<>>>><<><<>>><<<<>><<>><<<><<<<>><<<<><>>><<<<>>><<<>>>><<<>>>><<<<>>><<>>><<>>>><<<<>>>><<<<>><>>>><<<<>>><<>><>>><>>><<<<>>><<>>><>><<<>>>><<>>>><<<>>><<<>>>><<<<><<<><<>>><>><<<<>><>><<><<<<>>><<>>><<<>>>><<<<>>><<>>>><<<<>><>><<<><<>><<<>>>><<<>><<<<>>>><<<><<<<>>><<><>>><<>><<<>>><<<<>>><<>>>><<<>>><<<<>>><<>>>><<<<>><<>>>><<<>>>><<>>><<><<<>>><<<<>>>><<<<>>><<<>>>><<<<>><<<>>>><>>><><<>>><<<><<>>>><<<>>>><<><<<<>>>><<<><<>><<<<>>>><<>>><>>>><<<<>><<>>><<>>><<>><>><><<<<>>>><<<>><<>>><<><<<<>>>><<<<><<<<>>>><><<>>><><>>><<>>><>>><>>>><<>><><<>><>>><<>>>><<>>>><<<<><<<>>>><>><>>>><<<<><<<><<<>>>><<><<>><<<>>><<<<>>><<<<><<>>><<<>>>><<><<<<>><<<<>><<<><>><>>>><><<<>>><<<<><<<<>><>>><<<>><<<<><<<>>>><<<>>>><<<>><<>><<<<>><<<<>><>>>><<>>>><<<<>>><<>>>><<>>>><>><<<>>>><<<<>>><<<<><>>>><<><<<>><<<<>>>><<<<>><>>>><<<>>>><<<<>>>><<<<>>><<<<>><>>><<<<><>>>><<><>>>><>><<>>>><>>>><<>><<>>><<<>>>><<><<<>>>><<><<>><<<<>>><<<>>><<<<>><<<><<<>>><<><<>>>><<<>>><<>>><<<><<<<>>><>>>><<<>>><<<>>>><<><><<>>>><<>>>><<>>>><<>>><<>><<><<<>>><>>><<<<>>>><>>>><<<>><>><<<<>>><<<<>>><<>>><<<<><<<>>><>>>><<>><<<<>><<<<>><<<<><>><<<<>>>><<>>><>><<<>><<>><<<<>><<>>><<<<>>><<<<>>><<><<<>>><<><<<><<>>>><>><<><<<<><<>><<<>>>><><<<<><><><>>><<<>>><<>>><<<>>>><<><<>><<>><<<><<<<>>>><>>>><<>>>><<<>>>><<>>>><<<>><>><<<>>><<>>>><<><<>>>><<<><<<<>>><<<>>>><<<>>><<<><>>><<>>><<<>>>><<<>>>><<<>>>><<<>><>><<<>>><<<<>>>><><<<>>>><<>>>><><>>><<>>>><<>><<>>>><<<>><<<>>>><<>>>><<<<>><<<>><<<>><<>><<<>>><<><>>><<><<><>>>><<<>>>><<<<>><<>>>><<<<>><><<<>>><<<<>><<>>><<<>><<>><<>><>>>><<><<>>>><>>>><<><><<<><<<<>>>><<<<>><<><<><<>>>><>>><<<><<<<><<>><<<><<>><><<><<<>>>><>>>><<>>>><>><><><<<><<><<>>><<<<><<>><<<>>>><<><<<<>>>><<<<>><><<<<>><<>><>><<<<>>>><<>>>><<<<><<<>><<>>><<<>>><>>><<>>>><<<><<<<><<>>>><<<<>><<<>>>><<<>><<<<><<<>><<<<>><<<>>>><<>>>><><>>><>>><<<>>>><<>>><<<>><>>>><<<>>>><<<<><<<>>><<<<>><<>><<>><<<><<<<>>><><>><<<><<<>>><<<><<<<>>>><><<<<>><<>><>>><<<>>>><<>>><<<>><<<<>>><<<>><<>><<>><<<<><<>>><>><<>>><<><<<><<<>><<<<>>><>><><<<<>>>><<<><<<>><>><<>>>><<<>>>><<<><<<>>><<>>><><>><<<>><>>>><<<<>>>><<<<>>><<<<>>><<<<>><<<<><><<>><>><<>>><<>><<><<<<>>>><<<<>>>><<>>>><<<<>>>><<>>>><>>>><<>><<><<<><><>><<<><<<<>>>><<<<>><<<>>>><<<<>>>><>>>><><<<<>><>>><<<<><<>>>><>><<<<>><<<><<<>>>><<>><<>>><>>>><<><>>>><<<<><<><<<>>>><<<>>>><<><>><<<>><<<>><<<<><<>>><>><<>>><<>>><>>>><<<>>><<>><<><><<>>>><<<>>><<<>><<<>>><<<>>>><<>>><>>>><>>>><>>><<>>>><<<>><<<<>><<<<>><<>>>><><>>>><<>>>><<<><<<<><<>>>><<<<>><<<<>>>><><<<><>><<<<>>>><>>>><<<<>>>><<><>><<<<><<<>>><<<<>><>><>>>><<>>>><>>><>>>><>><<>>><<<><>><>>>><<<>><<<>><<<<><<<<>>><<<>>><<<>>>><>><>>><<<<>><<<><<>>><>>><<><>>>><<<>>>><<<<>>>><><<<>>><<<<>>><>><>>>><<<>><<>>>><>>><<<<>>>><<<>><<<>>>><<<<>><<<>>><<<<><<<<>>>><><<<>>><<<<>>>><<<<>><<>><<<>>><>>><>><<>>><<<>><><<><>><<>><>><<<><<<<>>><<<>><<<><<<>>>><<>>><<<<><<><<<>>><<<<>>><<>><>>><>>><<<><<>>>><<<>><<<<><<<>><<<<>><>><<>><>>>><>>>><<>>><<<<>>><><><><<<>>><<<>><<>>><<<<>>>><>><<<>>>><<>><<<<>><<>><>><<<>>>><>>><<<<>>><>><<>>><<<>><<<<>>>><<<>><<>><>><<<<>><<<><<<>><>><<<><<<>>>><<<<>>><<><<<<><<<<>>>><<<><>><<><>>><<<><<><<<<>>><<>>>><>><<<<>><<<<>>><<>>>><>>><<<>>><<<>>>><<>>><>>>><<<<><>><<>>>><<<>>><>>><>><<<>>>><<><<<>>>><<><<<<>>>><<<<>>>><><<<<>>>><<<>>>><<><<<>>>><<>><>><>>><<<<><<<>>>><<<<>>>><<<><<>>>><<<><>>>><<<<>>>><>>><<<>><<<<><<>>><<>>><<>>><>>><<<><><><<<>>>><<>>>><<<<><>>>><<<>><<>>>><<><<<<><<<<>><><<<<><<>>>><<<>><<<<>><<>><<><<>>>><<><<<><<<<><<<<>>><<<>>>><<<<>>><><<<>>><>>>><>>><<<<>>><<<>>><<<<><<<<><<>><><<<>>><>>><<><<><<>><<<<>>>><<<>><<<><<<<>>><<<<>>><<>><<<<>><>>>><>><<<><>>>><<<>>><<><<>><<<><<<>><<<<>><<<<>><<<<><>>>><<><<<>><<<><<<>><<<<><<>>>><<<>><<<><<<>>><<<><<<<>>>><<>>>><<<>><<<<>>><<><<<<>>>><<<<>>>><<>><<><<>>><<>>>><<>>><<>>><<<>>>><<>>><<><<>>><<<>><<<<>>><<>>><<<>>><<<>>><>>>><<<>>>><<<<>>>><>>>><<<>>>><<<>>>><>>>><>>>><<<><<>><><>><<>><><<<>>>><><>>>><><<<><>>><<<>>><<<>>><<<<>><<<<><<<>>><<>><<<<>>><<<>><<>>>><<><<<<>>><>><<<>>>><<>><<<<>>><<<<>>><>>>><<>" <> ...}
108
+
```
109
+
110
+
```elixir
111
+
well = [0, 0, 0, 0, 0, 0, 0]
112
+
```
113
+
114
+
<!-- livebook:{"output":true} -->
115
+
116
+
```
117
+
[0, 0, 0, 0, 0, 0, 0]
118
+
```
119
+
120
+
```elixir
121
+
defmodule Tetris do
122
+
def fit(well, n, :dash) when n in 0..3 do
123
+
max =
124
+
well
125
+
|> Enum.drop(n)
126
+
|> Enum.take(4)
127
+
|> Enum.max()
128
+
129
+
well
130
+
|> List.replace_at(n, max + 1)
131
+
|> List.replace_at(n + 1, max + 1)
132
+
|> List.replace_at(n + 2, max + 1)
133
+
|> List.replace_at(n + 3, max + 1)
134
+
end
135
+
136
+
def fit(well, n, :plus) when n in 0..4 do
137
+
bottom =
138
+
well
139
+
|> Enum.drop(n)
140
+
|> Enum.take(3)
141
+
|> case do
142
+
[a, b, c] when b < a and b < c -> max(a, b) - 1
143
+
[_, b, _] -> b
144
+
end
145
+
146
+
well
147
+
|> List.replace_at(n, bottom + 2)
148
+
|> List.replace_at(n + 1, bottom + 3)
149
+
|> List.replace_at(n + 2, bottom + 2)
150
+
end
151
+
152
+
def fit(well, n, :l), do: well
153
+
154
+
def fit(well, n, :i), do: well
155
+
156
+
def fit(well, n, :o), do: well
157
+
end
158
+
```
159
+
160
+
<!-- livebook:{"output":true} -->
161
+
162
+
```
163
+
warning: variable "n" is unused (if the variable is not meant to be used, prefix it with an underscore)
164
+
2022/day17.livemd#cell:yqwk3yzwldnf4hstvs2cj6qm5r3go5yp:32: Tetris.fit/3
165
+
166
+
warning: variable "n" is unused (if the variable is not meant to be used, prefix it with an underscore)
167
+
2022/day17.livemd#cell:yqwk3yzwldnf4hstvs2cj6qm5r3go5yp:34: Tetris.fit/3
168
+
169
+
warning: variable "n" is unused (if the variable is not meant to be used, prefix it with an underscore)
170
+
2022/day17.livemd#cell:yqwk3yzwldnf4hstvs2cj6qm5r3go5yp:36: Tetris.fit/3
171
+
172
+
```
173
+
174
+
<!-- livebook:{"output":true} -->
175
+
176
+
```
177
+
{:module, Tetris, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:fit, 3}}
178
+
```
179
+
180
+
```elixir
181
+
Tetris.fit([2, 1, 2, 0, 0, 0, 0], 0, :plus)
182
+
```
183
+
184
+
<!-- livebook:{"output":true} -->
185
+
186
+
```
187
+
[3, 4, 3, 0, 0, 0, 0]
188
+
```
+266
2022/day18.livemd
+266
2022/day18.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 18
4
+
5
+
```elixir
6
+
Mix.install([
7
+
{:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}
8
+
])
9
+
```
10
+
11
+
<!-- livebook:{"output":true} -->
12
+
13
+
```
14
+
:ok
15
+
```
16
+
17
+
## Section
18
+
19
+
<!-- livebook:{"attrs":{"day":"18","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
+
21
+
```elixir
22
+
{:ok, puzzle_input} =
23
+
KinoAOC.download_puzzle("2022", "18", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
24
+
```
25
+
26
+
<!-- livebook:{"output":true} -->
27
+
28
+
```
29
+
{:ok,
30
+
"9,2,13\n12,12,4\n3,8,14\n9,3,4\n15,5,7\n9,5,4\n7,3,10\n12,8,2\n8,12,16\n12,16,12\n5,15,8\n16,7,12\n4,5,6\n11,7,2\n10,14,16\n9,3,15\n6,7,3\n14,10,15\n7,12,3\n13,8,3\n9,1,12\n7,15,5\n8,6,16\n17,9,12\n3,13,6\n7,2,10\n9,14,3\n16,12,6\n13,4,15\n17,14,11\n14,4,5\n15,4,14\n3,4,9\n13,12,17\n15,11,3\n12,14,3\n12,5,4\n16,5,12\n14,16,6\n4,3,11\n9,16,13\n10,6,3\n17,9,7\n5,5,14\n14,13,15\n16,12,8\n7,11,2\n14,9,4\n12,11,15\n13,7,4\n4,15,13\n9,13,2\n7,16,9\n17,13,6\n11,0,11\n15,4,11\n4,12,8\n13,3,13\n5,12,17\n16,14,9\n6,5,4\n9,17,8\n6,10,2\n3,10,7\n1,9,7\n5,14,12\n7,12,5\n3,5,10\n5,15,14\n6,3,11\n15,13,13\n7,4,5\n11,7,4\n11,16,12\n2,11,8\n7,15,4\n9,5,17\n12,14,4\n14,4,6\n7,8,2\n11,3,7\n15,13,7\n12,11,2\n11,6,16\n18,10,10\n4,12,5\n11,10,2\n7,17,9\n3,14,9\n7,17,5\n10,8,17\n10,1,11\n11,11,1\n16,8,14\n2,7,10\n7,9,17\n12,12,2\n11,17,11\n15,10,16\n9,1,8\n1,10,12\n6,2,11\n17,11,8\n9,2,11\n13,5,4\n2,9,11\n4,5,9\n8,3,5\n3,14,11\n3,13,12\n10,8,16\n12,14,16\n15,12,13\n5,3,12\n16,9,12\n1,10,10\n17,6,10\n10,18,8\n8,13,17\n13,7,2\n3,12,13\n2,12,5\n6,9,16\n3,6,9\n6,16,6\n0,9,9\n6,17,10\n15,10,14\n2,8,12\n13,3,8\n11,12,17\n9,17,11\n4,6,8\n15,11,2\n4,6,15\n11,4,12\n11,8,1\n7,1,10\n12,11,3\n18,11,12\n8,16,12\n1,9,11\n16,14,14\n15,8,5\n15,5,5\n6,10,17\n13,4,16\n8,12,2\n10,5,15\n4,11,16\n4,10,4\n12,10,3\n10,5,2\n5,15,7\n14,15,7\n16,10,5\n6,3,3\n12,17,10\n4,7,14\n6,4,12\n13,5,11\n7,15,6\n1,8,9\n4,11,15\n14,4,4\n2,13,8\n5,4,5\n4,13,13\n4,14,8\n17,12,11\n7,16,15\n16,13,11\n11,3,12\n17,9,8\n11,6,15\n11,15,16\n6,17,9\n17,6,8\n13,15,15\n10,17,8\n3,5,5\n3,9,14\n17,10,13\n16,9,13\n13,8,16\n12,5,3\n12,15,15\n5,10,14\n16,15,11\n7,2,9\n9,16,12\n2,14,9\n14,17,8\n13,16,8\n7,3,5\n5,3,10\n11,5,16\n17,10,10\n6,7,16\n1,12,10\n6,14,2\n7,2,12\n12,17,9\n17,6,12\n2,13,13\n8,4,3\n16,8,13\n3,15,7\n16,5,13\n16,13,12\n16,12,5\n16,5,9\n4,13,8\n9,13,17\n13,10,15\n4,6,4\n10,11,17\n13,14,5\n9,14,14\n11,2,7\n12,10,2\n12,18,10\n12,6,16\n17,11,6\n8,14,16\n10,15,3\n3,6,5\n7,10,17\n15,5,12\n16,11,14\n8,12,18\n15,13,9\n6,8,3\n15,12,2\n14,13,6\n15,4,10\n11,1,8\n10,1,6\n5,7,16\n9,7,2\n13,3,6\n8,2,7\n14,14,5\n9,3,13\n6,3,8\n8,5,4\n7,4,4\n10,14,15\n10,16,5\n16,11,10\n3,8,11\n4,13,15\n8,13,5\n10,4,5\n15,14,14\n13,12,16\n11,14,3\n11,17,8\n6,5,2\n15,15,13\n5,5,5\n14,9,2\n5,5,9\n3,7,13\n2,15,9\n15,15,7\n7,17,8\n11,8,2\n16,5,7\n9,16,7\n11,4,4\n7,5,15\n10,12,1\n7,4,14\n9,16,6\n15,10,9\n14,7,16\n7,15,15\n15,11,5\n8,4,14\n13,14,10\n10,12,2\n11,15,14\n13,13,3\n4,13,4\n8,8,17\n9,4,3\n13,5,3\n2,10,8\n6,16,9\n4,8,14\n7,2,11\n14,1,10\n17,8,7\n14,9,13\n14,6,6\n5,6,16\n4,13,10\n8,13,16\n16,9,15\n5,8,3\n18,9,10\n13,14,15\n14,4,13\n17,12,10\n17,7,7\n10,17,6\n16,10,14\n6,11,2\n16,10,10\n12,8,16\n12,13,18\n12,2,8\n17,8,9\n12,6,4\n13,17,10\n17,6,6\n15,8,15\n7,17,13\n4,15,11\n10,12,17\n2,7,11\n17,13,10\n5,12,4\n11,3,13\n5,11,4\n14,3,10\n11,4,14\n10,1,13\n5,6,6\n2,10,12\n5,8,15\n13,7,3\n12,7,4\n15,14,7\n5,7,13\n8,6,3\n9,6,16\n16,5,11\n15,13,15\n9,14,17\n15,14,13\n14,5,6\n2,7,6\n13,15,5\n4,11,5\n8,4,6\n14,14,15\n17,5,10\n5,9,3\n11,5,4\n5,9,13\n16,8,15\n11,11,17\n10,3,4\n14,5,16\n6,9,15\n9,14,16\n9,5,5\n5,15,13\n9,11,3\n7,6,4\n12,13,3\n2,13,7\n10,13,17\n10,17,10\n13,3,9\n14,4,8\n18,8,8\n4,12,7\n6,17,12\n9,9,1\n16,8,12\n12,3,6\n6,5,14\n4,14,12\n15,11,13\n5,4,15\n4,15,12\n5,14,5\n10,4,16\n12,6,2\n15,13,4\n8,15,4\n14,5,14\n16,10,12\n6,17,11\n17,15,10\n16,13,10\n16,12,14\n10,14,3\n11,12,1\n4,10,14\n10,2,15\n16,13,14\n6,14,5\n2,9,7\n12,9,2\n8,18,11\n13,12,2\n7,9,3\n8,16,15\n12,3,15\n9,16,11\n16,9,7\n6,15,7\n12,2,13\n5,12,16\n6,12,17\n12,1,10\n11,13,14\n9,8,18\n15,10,17\n7,13,16\n11,2,11\n10,11,2\n13,16,14\n8,15,14\n8,4,13\n7,7,2\n13,10,1\n7,3,12\n12,2,10\n10,17,11\n3,13,9\n5,10,13\n10,10,16\n6,14,6\n7,6,2\n13,12,4\n15,3,13\n4,3,12\n7,10,18\n4,14,7\n15,9,4\n7,16,4\n11,3,6\n5,11,2\n2,9,13\n14,7,4\n14,15,10\n4,8,4\n7,6,16\n15,12,14\n17,7,10\n13,15,4\n16,4,8\n13,3,5\n6,16,8\n3,6,12\n6,16,7\n15,9,15\n4,6,10\n12,12,16\n2,8,10\n3,13,11\n8,5,6\n14,4,12\n10,9,18\n9,6,2\n6,9,3\n12,14,15\n10,5,12\n17,7,12\n7,11,17\n14,12,15\n18,9,8\n10,5,16\n14,9,16\n4,5,11\n5,13,8\n3,4,6\n2,6,11\n6,15,15\n9,5,2\n11,15,15\n7,16,13\n2,9,12\n1,9,10\n9,7,16\n9,11,17\n16,11,6\n14,16,8\n9,3,12\n8,14,4\n17,8,10\n17,5,9\n4,11,12\n3,5,13\n7,15,14\n11,8,17\n13,2,9\n10,17,12\n8,5,2\n16,16,12\n10,6,16\n16,6,7\n9,10,1\n9,16,15\n7,11,18\n4,9,16\n8,2,11\n7,16,11\n8,7,2\n7,9,2\n2,11,5\n6,3,7\n10,7,17\n6,5,16\n4,4,8\n11,9,4\n5,13,13\n14,6,14\n2,8,7\n14,5,5\n13,14,3\n15,14,8\n9,5,3\n16,4,11\n3,7,15\n7,16,12\n14,14,14\n4,9,5\n4,4,10\n2,14,12\n15,2,9\n9,15,4\n16,13,6\n7,7,3\n4,11,6\n1,12,9\n12,10,17\n5,12,14\n16,12,12\n6,6,5\n15,11,11\n11,4,5\n11,13,5\n18,13,9\n17,6,13\n12,4,12\n5,16,9\n10,9,17\n3,14" <> ...}
31
+
```
32
+
33
+
```elixir
34
+
cubes =
35
+
puzzle_input
36
+
|> String.split("\n", trim: true)
37
+
|> Enum.map(fn line ->
38
+
line
39
+
|> String.split(",")
40
+
|> Enum.map(&String.to_integer/1)
41
+
|> List.to_tuple()
42
+
end)
43
+
|> MapSet.new()
44
+
```
45
+
46
+
<!-- livebook:{"output":true} -->
47
+
48
+
```
49
+
MapSet.new([
50
+
{12, 9, 18},
51
+
{11, 4, 5},
52
+
{2, 10, 6},
53
+
{12, 2, 8},
54
+
{14, 15, 15},
55
+
{5, 14, 12},
56
+
{10, 6, 18},
57
+
{6, 4, 6},
58
+
{11, 4, 3},
59
+
{6, 14, 3},
60
+
{4, 8, 4},
61
+
{17, 7, 9},
62
+
{7, 12, 16},
63
+
{14, 13, 3},
64
+
{12, 3, 16},
65
+
{13, 6, 2},
66
+
{5, 6, 5},
67
+
{17, 10, 11},
68
+
{4, 16, 9},
69
+
{17, 9, 9},
70
+
{6, 2, 10},
71
+
{13, 17, 13},
72
+
{12, 13, 3},
73
+
{3, 13, 7},
74
+
{13, 7, 4},
75
+
{17, 12, 7},
76
+
{7, 3, 13},
77
+
{12, 15, 15},
78
+
{15, 6, 4},
79
+
{17, 10, 8},
80
+
{9, 14, 13},
81
+
{3, 9, 4},
82
+
{14, 13, 9},
83
+
{15, 13, 4},
84
+
{13, 4, 15},
85
+
{7, 7, 15},
86
+
{6, 14, 8},
87
+
{11, 2, 16},
88
+
{7, 2, 8},
89
+
{3, 14, 13},
90
+
{4, 5, 6},
91
+
{3, 9, 14},
92
+
{4, 16, 12},
93
+
{14, 12, 12},
94
+
{14, 5, 15},
95
+
{17, 9, 12},
96
+
{15, 10, 15},
97
+
{8, 17, ...},
98
+
{2, ...},
99
+
{...},
100
+
...
101
+
])
102
+
```
103
+
104
+
## Task 1
105
+
106
+
```elixir
107
+
sides =
108
+
for {x, y, z} <- cubes,
109
+
{place, {dx, dy, dz}} <- [
110
+
x: {-1, 0, 0},
111
+
y: {0, -1, 0},
112
+
z: {0, 0, -1},
113
+
x: {0, 0, 0},
114
+
y: {0, 0, 0},
115
+
z: {0, 0, 0}
116
+
],
117
+
reduce: MapSet.new() do
118
+
set ->
119
+
side = {place, {x + dx, y + dy, z + dz}}
120
+
121
+
if side in set do
122
+
MapSet.delete(set, side)
123
+
else
124
+
MapSet.put(set, side)
125
+
end
126
+
end
127
+
128
+
MapSet.size(sides)
129
+
```
130
+
131
+
<!-- livebook:{"output":true} -->
132
+
133
+
```
134
+
3636
135
+
```
136
+
137
+
## Task 2
138
+
139
+
```elixir
140
+
max =
141
+
Enum.reduce(cubes, {0, 0, 0}, fn {x, y, z}, {mx, my, mz} ->
142
+
{max(x, mx), max(y, my), max(z, mz)}
143
+
end)
144
+
```
145
+
146
+
<!-- livebook:{"output":true} -->
147
+
148
+
```
149
+
{19, 19, 19}
150
+
```
151
+
152
+
```elixir
153
+
defmodule Cave do
154
+
def bfs([], _sides, outer, _visited), do: outer
155
+
156
+
def bfs([{x, y, z} = p | queue], sides, outer, visited) do
157
+
{min, max} = Enum.min_max([x, y, z])
158
+
159
+
if p in visited or max > 25 or min < -5 do
160
+
bfs(queue, sides, outer, visited)
161
+
else
162
+
visited = MapSet.put(visited, p)
163
+
164
+
{outer, xs1} = check(:x, p, {x + 1, y, z}, sides, outer, visited)
165
+
{outer, xs2} = check(:x, {x - 1, y, z}, {x - 1, y, z}, sides, outer, visited)
166
+
{outer, ys1} = check(:y, p, {x, y + 1, z}, sides, outer, visited)
167
+
{outer, ys2} = check(:y, {x, y - 1, z}, {x, y - 1, z}, sides, outer, visited)
168
+
{outer, zs1} = check(:z, p, {x, y, z + 1}, sides, outer, visited)
169
+
{outer, zs2} = check(:z, {x, y, z - 1}, {x, y, z - 1}, sides, outer, visited)
170
+
171
+
bfs(queue ++ xs1 ++ xs2 ++ ys1 ++ ys2 ++ zs1 ++ zs2, sides, outer, visited)
172
+
end
173
+
end
174
+
175
+
defp check(axis, curr, next, sides, outer, visited) do
176
+
cond do
177
+
{axis, curr} in sides ->
178
+
{MapSet.put(outer, {axis, curr}), []}
179
+
180
+
next in visited ->
181
+
{outer, []}
182
+
183
+
true ->
184
+
{outer, [next]}
185
+
end
186
+
end
187
+
end
188
+
```
189
+
190
+
<!-- livebook:{"output":true} -->
191
+
192
+
```
193
+
{:module, Cave, <<70, 79, 82, 49, 0, 0, 14, ...>>, {:check, 6}}
194
+
```
195
+
196
+
```elixir
197
+
outer = Cave.bfs([{-5, -5, -5}], sides, MapSet.new(), MapSet.new())
198
+
```
199
+
200
+
<!-- livebook:{"output":true} -->
201
+
202
+
```
203
+
MapSet.new([
204
+
x: {10, 19, 11},
205
+
z: {15, 16, 12},
206
+
z: {2, 16, 10},
207
+
z: {5, 13, 2},
208
+
y: {4, 3, 15},
209
+
x: {0, 13, 10},
210
+
x: {17, 12, 6},
211
+
z: {10, 11, 0},
212
+
z: {10, 5, 17},
213
+
z: {4, 7, 2},
214
+
x: {15, 16, 9},
215
+
x: {2, 7, 4},
216
+
z: {2, 8, 5},
217
+
y: {16, 13, 5},
218
+
x: {2, 6, 14},
219
+
x: {18, 12, 11},
220
+
y: {13, 17, 7},
221
+
z: {3, 9, 14},
222
+
y: {11, 3, 16},
223
+
x: {4, 10, 17},
224
+
y: {11, 2, 15},
225
+
z: {13, 4, 3},
226
+
x: {10, 17, 5},
227
+
y: {3, 12, 4},
228
+
y: {11, 18, 10},
229
+
z: {5, 17, 8},
230
+
y: {15, 16, 6},
231
+
y: {3, 3, 7},
232
+
z: {7, 1, 5},
233
+
x: {14, 2, 9},
234
+
y: {18, 5, 8},
235
+
x: {10, 1, 13},
236
+
x: {9, 16, 3},
237
+
x: {2, 15, 8},
238
+
y: {7, 4, 2},
239
+
x: {17, 6, 12},
240
+
x: {0, 9, 7},
241
+
x: {12, 8, 1},
242
+
x: {0, 11, 10},
243
+
z: {10, 16, 3},
244
+
x: {16, 5, 6},
245
+
z: {5, 10, 1},
246
+
z: {7, 4, 15},
247
+
z: {12, 11, 18},
248
+
y: {11, 17, 12},
249
+
z: {3, 5, 4},
250
+
z: {6, 1, 9},
251
+
x: {16, 8, ...},
252
+
z: {14, ...},
253
+
z: {...},
254
+
...
255
+
])
256
+
```
257
+
258
+
```elixir
259
+
MapSet.size(outer)
260
+
```
261
+
262
+
<!-- livebook:{"output":true} -->
263
+
264
+
```
265
+
2102
266
+
```
+230
2022/day19.livemd
+230
2022/day19.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 19
4
+
5
+
```elixir
6
+
Mix.install([
7
+
{:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}
8
+
])
9
+
```
10
+
11
+
<!-- livebook:{"output":true} -->
12
+
13
+
```
14
+
:ok
15
+
```
16
+
17
+
## Section
18
+
19
+
<!-- livebook:{"attrs":{"day":"19","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
+
21
+
```elixir
22
+
{:ok, puzzle_input} =
23
+
KinoAOC.download_puzzle("2022", "19", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
24
+
```
25
+
26
+
<!-- livebook:{"output":true} -->
27
+
28
+
```
29
+
{:ok,
30
+
"Blueprint 1: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 2 ore and 8 obsidian.\nBlueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 10 obsidian.\nBlueprint 3: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 14 obsidian.\nBlueprint 4: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 15 obsidian.\nBlueprint 5: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 6: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 7: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 3 ore and 7 obsidian.\nBlueprint 8: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 8 obsidian.\nBlueprint 9: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 4 ore and 18 obsidian.\nBlueprint 10: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 2 ore and 19 obsidian.\nBlueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 3 ore and 10 obsidian.\nBlueprint 12: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 2 ore and 16 obsidian.\nBlueprint 13: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 14: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 13 obsidian.\nBlueprint 15: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 2 ore and 20 obsidian.\nBlueprint 16: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 4 ore and 10 obsidian.\nBlueprint 17: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 16 obsidian.\nBlueprint 18: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 2 ore and 17 obsidian.\nBlueprint 19: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 4 ore and 12 obsidian.\nBlueprint 20: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 16 clay. Each geode robot costs 3 ore and 20 obsidian.\nBlueprint 21: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 12 obsidian.\nBlueprint 22: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 3 ore and 19 obsidian.\nBlueprint 23: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 8 obsidian.\nBlueprint 24: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 2 ore and 9 obsidian.\nBlueprint 25: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 26: Each ore robot costs 4 ore. Each clay robot costs " <> ...}
31
+
```
32
+
33
+
```elixir
34
+
puzzle_input = """
35
+
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
36
+
Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.
37
+
"""
38
+
```
39
+
40
+
<!-- livebook:{"output":true} -->
41
+
42
+
```
43
+
"Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.\n"
44
+
```
45
+
46
+
```elixir
47
+
regex =
48
+
~r/ore robot.*(?<ore_ore>\d+) ore.*clay robot.*(?<clay_ore>\d+) ore.*obsidian robot.*(?<obsidian_ore>\d+) ore and (?<obsidian_clay>\d+) clay.*geode robot.*(?<geode_ore>\d+) ore and (?<geode_obsidian>\d+) obsidian/
49
+
50
+
plans =
51
+
puzzle_input
52
+
|> String.split("\n", trim: true)
53
+
|> Kino.render()
54
+
|> Enum.map(fn line ->
55
+
blueprint =
56
+
Regex.named_captures(regex, line)
57
+
|> Map.new(fn {k, v} ->
58
+
{String.to_atom(k), String.to_integer(v)}
59
+
end)
60
+
61
+
%{
62
+
ore: %{ore: blueprint.ore_ore},
63
+
clay: %{ore: blueprint.clay_ore},
64
+
obsidian: %{ore: blueprint.obsidian_ore, clay: blueprint.obsidian_clay},
65
+
geode: %{ore: blueprint.geode_ore, obsidian: blueprint.geode_obsidian},
66
+
max: %{
67
+
ore:
68
+
Enum.max([
69
+
blueprint.ore_ore,
70
+
blueprint.clay_ore,
71
+
blueprint.obsidian_ore,
72
+
blueprint.geode_ore
73
+
]),
74
+
clay: blueprint.obsidian_clay,
75
+
obsidian: blueprint.geode_obsidian
76
+
}
77
+
}
78
+
end)
79
+
```
80
+
81
+
<!-- livebook:{"output":true} -->
82
+
83
+
```
84
+
["Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.",
85
+
"Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian."]
86
+
```
87
+
88
+
<!-- livebook:{"output":true} -->
89
+
90
+
```
91
+
[
92
+
%{
93
+
clay: %{ore: 2},
94
+
geode: %{obsidian: 7, ore: 2},
95
+
max: %{clay: 14, obsidian: 7, ore: 4},
96
+
obsidian: %{clay: 14, ore: 3},
97
+
ore: %{ore: 4}
98
+
},
99
+
%{
100
+
clay: %{ore: 3},
101
+
geode: %{obsidian: 12, ore: 3},
102
+
max: %{clay: 8, obsidian: 12, ore: 3},
103
+
obsidian: %{clay: 8, ore: 3},
104
+
ore: %{ore: 2}
105
+
}
106
+
]
107
+
```
108
+
109
+
```elixir
110
+
defmodule Blueprint do
111
+
def produce(plan, time, machines) do
112
+
produce(plan, time, machines, %{ore: 0, clay: 0, obsidian: 0, geode: 0})
113
+
end
114
+
115
+
def produce(_plan, 0, machines, stash) do
116
+
%{machines: machines, stash: stash}
117
+
end
118
+
119
+
def produce(plan, time_left, machines, stash) do
120
+
do_shopping(plan, stash)
121
+
|> Enum.filter(fn {k, _} -> (machines[k] || 0) < plan.max[k] end)
122
+
|> Enum.flat_map(fn {machine, new_stash} ->
123
+
# if machine in [:obsidian, :geode], do: IO.inspect(new_stash)
124
+
[
125
+
produce(
126
+
plan,
127
+
time_left - 1,
128
+
add_machine(machine, machines),
129
+
update_stash(machines, new_stash)
130
+
)
131
+
]
132
+
end)
133
+
# |> tap(fn list ->
134
+
# Enum.filter(list, & &1.obsidian > 0)
135
+
# |> Enum.map(&IO.inspect/1)
136
+
# end)
137
+
|> Enum.max_by(& &1.stash.geode)
138
+
end
139
+
140
+
defp add_machine(nil, machines), do: machines
141
+
defp add_machine(name, machines), do: Map.update(machines, name, 1, &(&1 + 1))
142
+
143
+
defp update_stash(machines, stash) do
144
+
Enum.reduce(machines, stash, fn {k, v}, acc ->
145
+
Map.update(acc, k, v, &(&1 + v))
146
+
end)
147
+
end
148
+
149
+
def do_shopping(plan, stash)
150
+
when stash.ore >= plan.geode.ore and stash.obsidian >= plan.geode.obsidian,
151
+
do: [{:geode, buy(plan.geode, stash)}]
152
+
153
+
def do_shopping(plan, stash)
154
+
when stash.ore >= plan.obsidian.ore and stash.clay >= plan.obsidian.clay,
155
+
do: [{:obsidian, buy(plan.obsidian, stash)}, {nil, stash}]
156
+
157
+
def do_shopping(plan, stash) do
158
+
[
159
+
{nil, stash}
160
+
| Enum.flat_map([:ore, :clay], fn k ->
161
+
if stash.ore >= plan[k].ore do
162
+
[{k, %{stash | ore: stash.ore - plan[k].ore}}]
163
+
else
164
+
[]
165
+
end
166
+
end)
167
+
]
168
+
end
169
+
170
+
defp buy(price, stash) do
171
+
Map.merge(stash, price, fn _k, v1, v2 -> v1 - v2 end)
172
+
end
173
+
end
174
+
```
175
+
176
+
<!-- livebook:{"output":true} -->
177
+
178
+
```
179
+
{:module, Blueprint, <<70, 79, 82, 49, 0, 0, 22, ...>>, {:buy, 2}}
180
+
```
181
+
182
+
```elixir
183
+
plan = hd(plans) |> Kino.inspect()
184
+
stash = %{clay: 35, geode: 0, obsidian: 0, ore: 4}
185
+
186
+
Blueprint.do_shopping(plan, stash)
187
+
```
188
+
189
+
<!-- livebook:{"output":true} -->
190
+
191
+
```
192
+
%{
193
+
clay: %{ore: 2},
194
+
geode: %{obsidian: 7, ore: 2},
195
+
max: %{clay: 14, obsidian: 7, ore: 4},
196
+
obsidian: %{clay: 14, ore: 3},
197
+
ore: %{ore: 4}
198
+
}
199
+
```
200
+
201
+
<!-- livebook:{"output":true} -->
202
+
203
+
```
204
+
[
205
+
obsidian: %{clay: 21, geode: 0, obsidian: 0, ore: 1},
206
+
nil: %{clay: 35, geode: 0, obsidian: 0, ore: 4}
207
+
]
208
+
```
209
+
210
+
```elixir
211
+
plans
212
+
# |> Enum.drop(1)
213
+
|> Enum.take(1)
214
+
|> Kino.inspect()
215
+
|> Enum.map(fn plan -> Blueprint.produce(plan, 24, %{ore: 1}) end)
216
+
```
217
+
218
+
<!-- livebook:{"output":true} -->
219
+
220
+
```
221
+
[
222
+
%{
223
+
clay: %{ore: 2},
224
+
geode: %{obsidian: 7, ore: 2},
225
+
max: %{clay: 14, obsidian: 7, ore: 4},
226
+
obsidian: %{clay: 14, ore: 3},
227
+
ore: %{ore: 4}
228
+
}
229
+
]
230
+
```
+15
2022/day20.livemd
+15
2022/day20.livemd
+78
-1
2022/day21.livemd
+78
-1
2022/day21.livemd
···
11
11
<!-- livebook:{"output":true} -->
12
12
13
13
```
14
+
* Getting kino_aoc (https://github.com/ljgago/kino_aoc)
15
+
remote: Enumerating objects: 78, done.
16
+
remote: Counting objects: 100% (78/78), done.
17
+
remote: Compressing objects: 100% (50/50), done.
18
+
remote: Total 78 (delta 25), reused 67 (delta 18), pack-reused 0
19
+
origin/HEAD set to main
20
+
Resolving Hex dependencies...
21
+
Dependency resolution completed:
22
+
New:
23
+
castore 0.1.20
24
+
finch 0.14.0
25
+
hpax 0.1.2
26
+
jason 1.4.0
27
+
kino 0.8.0
28
+
mime 2.0.3
29
+
mint 1.4.2
30
+
nimble_options 0.5.2
31
+
nimble_pool 0.2.6
32
+
req 0.3.4
33
+
table 0.1.2
34
+
telemetry 1.2.0
35
+
* Getting kino (Hex package)
36
+
* Getting req (Hex package)
37
+
* Getting finch (Hex package)
38
+
* Getting jason (Hex package)
39
+
* Getting mime (Hex package)
40
+
* Getting castore (Hex package)
41
+
* Getting mint (Hex package)
42
+
* Getting nimble_options (Hex package)
43
+
* Getting nimble_pool (Hex package)
44
+
* Getting telemetry (Hex package)
45
+
* Getting hpax (Hex package)
46
+
* Getting table (Hex package)
47
+
==> table
48
+
Compiling 5 files (.ex)
49
+
Generated table app
50
+
==> mime
51
+
Compiling 1 file (.ex)
52
+
Generated mime app
53
+
==> nimble_options
54
+
Compiling 3 files (.ex)
55
+
Generated nimble_options app
56
+
==> kino
57
+
Compiling 37 files (.ex)
58
+
Generated kino app
59
+
===> Analyzing applications...
60
+
===> Compiling telemetry
61
+
==> jason
62
+
Compiling 10 files (.ex)
63
+
Generated jason app
64
+
==> hpax
65
+
Compiling 4 files (.ex)
66
+
Generated hpax app
67
+
==> nimble_pool
68
+
Compiling 2 files (.ex)
69
+
Generated nimble_pool app
70
+
==> castore
71
+
Compiling 1 file (.ex)
72
+
Generated castore app
73
+
==> mint
74
+
Compiling 1 file (.erl)
75
+
Compiling 19 files (.ex)
76
+
Generated mint app
77
+
==> finch
78
+
Compiling 13 files (.ex)
79
+
Generated finch app
80
+
==> req
81
+
Compiling 5 files (.ex)
82
+
Generated req app
83
+
==> kino_aoc
84
+
Compiling 3 files (.ex)
85
+
Generated kino_aoc app
86
+
```
87
+
88
+
<!-- livebook:{"output":true} -->
89
+
90
+
```
14
91
:ok
15
92
```
16
93
17
94
## Section
18
95
19
-
<!-- livebook:{"attrs":{"day":"21","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
96
+
<!-- livebook:{"attrs":{"day":"21","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
97
21
98
```elixir
22
99
{:ok, puzzle_input} =
+15
2022/day22.livemd
+15
2022/day22.livemd
+15
2022/day23.livemd
+15
2022/day23.livemd
+15
2022/day24.livemd
+15
2022/day24.livemd