+69
2021/day1.livemd
+69
2021/day1.livemd
···
1
+
<!-- vim:ft=markdown -->
2
+
3
+
<!-- livebook:{"persist_outputs":true} -->
4
+
5
+
# Day 1
6
+
7
+
## Load input
8
+
9
+
```elixir
10
+
stream =
11
+
File.stream!("day1.txt")
12
+
|> Stream.map(&String.to_integer(String.trim(&1)))
13
+
```
14
+
15
+
```output
16
+
#Stream<[
17
+
enum: %File.Stream{
18
+
line_or_bytes: :line,
19
+
modes: [:raw, :read_ahead, :binary],
20
+
path: "day1.txt",
21
+
raw: true
22
+
},
23
+
funs: [#Function<47.58486609/1 in Stream.map/2>]
24
+
]>
25
+
```
26
+
27
+
## Task 1
28
+
29
+
Compute count of consecutive increases
30
+
31
+
```elixir
32
+
stream
33
+
|> Stream.chunk_every(2, 1, :discard)
34
+
|> Enum.count(fn [a, b] -> a < b end)
35
+
```
36
+
37
+
```output
38
+
1688
39
+
```
40
+
41
+
## Task 2
42
+
43
+
Compute count of consecutive increases of sums of trigrams.
44
+
45
+
However we can notice, that if we have list like:
46
+
47
+
$$
48
+
[a, b, c, d]
49
+
$$
50
+
51
+
Then when we want to compare consecutive trigrams then we compare:
52
+
53
+
$$
54
+
a + b + c < b + c + d \\
55
+
a < d
56
+
$$
57
+
58
+
So we can traverse each 4 elements and then just compare first and last one
59
+
instead of summing and then traversing it again.
60
+
61
+
```elixir
62
+
stream
63
+
|> Stream.chunk_every(4, 1, :discard)
64
+
|> Enum.count(fn [a, _, _, b] -> a < b end)
65
+
```
66
+
67
+
```output
68
+
1728
69
+
```
+88
2021/day10.livemd
+88
2021/day10.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 10
7
+
8
+
```elixir
9
+
input =
10
+
File.stream!("day10.txt")
11
+
|> Stream.map(&String.trim/1)
12
+
13
+
defmodule Day10 do
14
+
@parens %{?( => ?), ?[ => ?], ?< => ?>, ?{ => ?}}
15
+
16
+
def parse(input), do: parse(input, [])
17
+
18
+
defp parse(<<c>> <> rest, stack) when c in '([{<', do: parse(rest, [@parens[c] | stack])
19
+
defp parse(<<c>> <> rest, [c | stack]), do: parse(rest, stack)
20
+
defp parse(<<>>, []), do: :ok
21
+
defp parse(<<>>, rest), do: {:incomplete, rest}
22
+
defp parse(<<c>> <> _, _), do: {:unexpected, [c]}
23
+
end
24
+
```
25
+
26
+
```output
27
+
{:module, Day10, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:parse, 2}}
28
+
```
29
+
30
+
## Task 1
31
+
32
+
```elixir
33
+
points = %{
34
+
?) => 3,
35
+
?] => 57,
36
+
?} => 1197,
37
+
?> => 25137
38
+
}
39
+
40
+
input
41
+
|> Enum.map(&Day10.parse/1)
42
+
|> Enum.map(fn
43
+
{:unexpected, [c]} -> points[c]
44
+
_ -> 0
45
+
end)
46
+
|> Enum.sum()
47
+
```
48
+
49
+
```output
50
+
288291
51
+
```
52
+
53
+
## Task 2
54
+
55
+
```elixir
56
+
points = %{
57
+
?) => 1,
58
+
?] => 2,
59
+
?} => 3,
60
+
?> => 4
61
+
}
62
+
63
+
median = fn list ->
64
+
sorted = Enum.sort(list)
65
+
middle = div(length(list), 2)
66
+
67
+
Enum.at(sorted, middle)
68
+
end
69
+
70
+
input
71
+
|> Enum.map(&Day10.parse/1)
72
+
|> Enum.flat_map(fn
73
+
{:incomplete, rest} ->
74
+
[
75
+
Enum.reduce(rest, 0, fn c, acc ->
76
+
acc * 5 + points[c]
77
+
end)
78
+
]
79
+
80
+
_ ->
81
+
[]
82
+
end)
83
+
|> median.()
84
+
```
85
+
86
+
```output
87
+
820045242
88
+
```
+101
2021/day11.livemd
+101
2021/day11.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 11
7
+
8
+
```elixir
9
+
input =
10
+
File.read!("day11.txt")
11
+
|> String.split("\n")
12
+
|> Enum.map(&String.trim/1)
13
+
|> Enum.map(fn line ->
14
+
for <<c <- line>>, do: c - ?0
15
+
end)
16
+
|> Enum.with_index()
17
+
|> Enum.flat_map(fn {row, y} ->
18
+
for {v, x} <- Enum.with_index(row), do: {{x, y}, v}
19
+
end)
20
+
|> Map.new()
21
+
22
+
defmodule Day11 do
23
+
def step(map) do
24
+
updated = Map.new(map, fn {k, v} -> {k, v + 1} end)
25
+
26
+
lightup(updated, 0)
27
+
end
28
+
29
+
@diffs for dx <- -1..1, dy <- -1..1, dx != 0 or dy != 0, do: {dx, dy}
30
+
31
+
def lightup(map, n) do
32
+
map
33
+
|> Enum.reduce({map, 0}, fn
34
+
{_, v}, acc when v < 10 ->
35
+
acc
36
+
37
+
{{x, y} = k, _}, {map, count} ->
38
+
new_map =
39
+
@diffs
40
+
|> Enum.reduce(map, fn {dx, dy}, acc ->
41
+
point = {x + dx, y + dy}
42
+
43
+
case Map.fetch(acc, point) do
44
+
{:ok, value} when value != 0 -> %{acc | point => value + 1}
45
+
_ -> acc
46
+
end
47
+
end)
48
+
|> Map.put(k, 0)
49
+
50
+
{new_map, count + 1}
51
+
end)
52
+
|> case do
53
+
{map, 0} -> {map, n}
54
+
{map, m} -> lightup(map, n + m)
55
+
end
56
+
end
57
+
end
58
+
```
59
+
60
+
```output
61
+
{:module, Day11, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:lightup, 2}}
62
+
```
63
+
64
+
## Task 1
65
+
66
+
```elixir
67
+
draw = fn map ->
68
+
for x <- 0..9 do
69
+
IO.puts(for y <- 0..9, do: ?0 + map[{x, y}])
70
+
end
71
+
72
+
IO.puts("")
73
+
end
74
+
75
+
1..100
76
+
|> Enum.reduce({input, 0}, fn _, {map, n} ->
77
+
{new_map, m} = Day11.step(map)
78
+
{new_map, n + m}
79
+
end)
80
+
|> elem(1)
81
+
```
82
+
83
+
```output
84
+
1688
85
+
```
86
+
87
+
## Task 2
88
+
89
+
```elixir
90
+
Stream.unfold(1, &{&1, &1 + 1})
91
+
|> Enum.reduce_while(input, fn idx, map ->
92
+
case Day11.step(map) do
93
+
{_, 100} -> {:halt, idx}
94
+
{next, _} -> {:cont, next}
95
+
end
96
+
end)
97
+
```
98
+
99
+
```output
100
+
403
101
+
```
+83
2021/day12.livemd
+83
2021/day12.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 12
7
+
8
+
```elixir
9
+
input =
10
+
File.read!("day12.txt")
11
+
|> String.split("\n")
12
+
|> Enum.map(&String.split(&1, "-"))
13
+
14
+
graph =
15
+
Enum.reduce(input, %{}, fn [a, b], acc ->
16
+
acc
17
+
|> Map.update(a, [b], &[b | &1])
18
+
|> Map.update(b, [a], &[a | &1])
19
+
end)
20
+
21
+
defmodule Day12 do
22
+
def dfs(graph, start, finish), do: dfs(graph, start, finish, [start])
23
+
24
+
defp dfs(_graph, vertex, vertex, _visited), do: 1
25
+
26
+
defp dfs(graph, vertex, finish, visited) do
27
+
(graph[vertex] -- visited)
28
+
|> Enum.reduce(0, fn vertex, acc ->
29
+
visited = if small?(vertex), do: [vertex | visited], else: visited
30
+
31
+
acc + dfs(graph, vertex, finish, visited)
32
+
end)
33
+
end
34
+
35
+
def dfs2(graph, start, finish), do: dfs2(graph, start, finish, %{start => :inf})
36
+
37
+
defp dfs2(_graph, vertex, vertex, _visited), do: 1
38
+
39
+
defp dfs2(graph, vertex, finish, visited) do
40
+
(graph[vertex] -- keys(visited))
41
+
|> Enum.reduce(0, fn vertex, acc ->
42
+
visited = if small?(vertex), do: Map.update(visited, vertex, 1, &(&1 + 1)), else: visited
43
+
44
+
acc + dfs2(graph, vertex, finish, visited)
45
+
end)
46
+
end
47
+
48
+
defp keys(map) do
49
+
if Enum.any?(map, fn {_, v} -> v == 2 end) do
50
+
# there is already some vertex visited twice
51
+
Map.keys(map)
52
+
else
53
+
for {k, v} <- map, v > 1, do: k
54
+
end
55
+
end
56
+
57
+
defp small?(<<c>> <> _), do: c in ?a..?z
58
+
end
59
+
```
60
+
61
+
```output
62
+
{:module, Day12, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:small?, 1}}
63
+
```
64
+
65
+
## Task 1
66
+
67
+
```elixir
68
+
Day12.dfs(graph, "start", "end")
69
+
```
70
+
71
+
```output
72
+
4167
73
+
```
74
+
75
+
## Task 2
76
+
77
+
```elixir
78
+
Day12.dfs2(graph, "start", "end")
79
+
```
80
+
81
+
```output
82
+
98441
83
+
```
+99
2021/day13.livemd
+99
2021/day13.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 13
7
+
8
+
```elixir
9
+
[input, folds] =
10
+
File.read!("day13.txt")
11
+
|> String.trim()
12
+
|> String.split("\n\n")
13
+
14
+
input =
15
+
input
16
+
|> String.split("\n")
17
+
|> Enum.map(fn line ->
18
+
[x, y] = String.split(line, ",")
19
+
20
+
{String.to_integer(x), String.to_integer(y)}
21
+
end)
22
+
|> MapSet.new()
23
+
24
+
folds =
25
+
folds
26
+
|> String.split("\n")
27
+
|> Enum.map(fn
28
+
"fold along " <> <<c>> <> "=" <> rest ->
29
+
{String.to_atom(<<c>>), String.to_integer(rest)}
30
+
end)
31
+
32
+
defmodule Day13 do
33
+
def fold({orientation, pos}, set) do
34
+
Enum.reduce(set, MapSet.new(), fn point, acc ->
35
+
new_point = folded_coords(orientation, pos, point)
36
+
37
+
MapSet.put(acc, new_point)
38
+
end)
39
+
end
40
+
41
+
defp folded_coords(:x, col, {x, y}) when x > col, do: {abs(2 * col - x), y}
42
+
defp folded_coords(:y, row, {x, y}) when y > row, do: {x, abs(2 * row - y)}
43
+
defp folded_coords(_, _, point), do: point
44
+
45
+
def draw(set) do
46
+
set
47
+
|> Enum.group_by(&elem(&1, 1))
48
+
|> Enum.sort()
49
+
|> Enum.map(fn {_, points} ->
50
+
points
51
+
|> Enum.map(&elem(&1, 0))
52
+
|> Enum.sort()
53
+
|> Enum.chunk_every(2, 1)
54
+
|> Enum.map(fn
55
+
[a, b] -> b - a
56
+
_ -> 0
57
+
end)
58
+
|> Enum.map(&String.pad_trailing("█", &1, " "))
59
+
end)
60
+
|> Enum.join("\n")
61
+
end
62
+
end
63
+
```
64
+
65
+
```output
66
+
{:module, Day13, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:draw, 1}}
67
+
```
68
+
69
+
## Task 1
70
+
71
+
```elixir
72
+
Day13.fold(hd(folds), input) |> MapSet.size()
73
+
```
74
+
75
+
```output
76
+
802
77
+
```
78
+
79
+
## Task 2
80
+
81
+
```elixir
82
+
Enum.reduce(folds, input, &Day13.fold/2)
83
+
|> Day13.draw()
84
+
|> IO.puts()
85
+
```
86
+
87
+
```output
88
+
███ █ █ █ █ ████ ████ ██ █ █ ███
89
+
█ █ █ █ █ █ █ █ █ █ █ █ █ █
90
+
█ █ ██ ████ ███ █ █ █ █ ███
91
+
███ █ █ █ █ █ █ █ ██ █ █ █ █
92
+
█ █ █ █ █ █ █ █ █ █ █ █ █ █
93
+
█ █ █ █ █ █ █ ████ ███ ██ ███
94
+
```
95
+
96
+
```output
97
+
:ok
98
+
```
99
+
+102
2021/day14.livemd
+102
2021/day14.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 14
7
+
8
+
```elixir
9
+
[polymer_raw, subs] =
10
+
File.read!("day14.txt")
11
+
|> String.split("\n\n")
12
+
13
+
<<first, _::binary>> = polymer_raw
14
+
15
+
polymer =
16
+
{first,
17
+
polymer_raw
18
+
|> String.to_charlist()
19
+
|> Enum.chunk_every(2, 1, :discard)
20
+
|> Enum.frequencies()}
21
+
22
+
subs =
23
+
subs
24
+
|> String.trim()
25
+
|> String.split(["\n", " -> "])
26
+
|> Enum.chunk_every(2)
27
+
|> Map.new(fn [pair, <<new>>] -> {String.to_charlist(pair), new} end)
28
+
29
+
defmodule Day14 do
30
+
def expand({hd, polymer}, subs) do
31
+
new =
32
+
polymer
33
+
|> Enum.reduce(%{}, fn {[a, b] = pair, count}, acc ->
34
+
s = Map.fetch!(subs, pair)
35
+
36
+
acc
37
+
|> Map.update([a, s], count, &(&1 + count))
38
+
|> Map.update([s, b], count, &(&1 + count))
39
+
end)
40
+
41
+
{hd, new}
42
+
end
43
+
44
+
def expand_naive(polymer, subs) do
45
+
polymer
46
+
|> to_charlist()
47
+
|> Enum.chunk_every(2, 1, :discard)
48
+
|> Enum.flat_map(fn [a, b] = pair ->
49
+
[a, subs[pair], b]
50
+
end)
51
+
|> List.to_string()
52
+
end
53
+
54
+
def frequencies({hd, polymer}) do
55
+
polymer
56
+
|> Enum.reduce(%{hd => 1}, fn {[_, b], count}, acc ->
57
+
Map.update(acc, b, count, &(&1 + count))
58
+
end)
59
+
end
60
+
end
61
+
```
62
+
63
+
```output
64
+
{:module, Day14, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:frequencies, 1}}
65
+
```
66
+
67
+
## Task 1
68
+
69
+
```elixir
70
+
{{_, min}, {_, max}} =
71
+
1..10
72
+
|> Enum.reduce(polymer, fn _, acc ->
73
+
Day14.expand(acc, subs)
74
+
end)
75
+
|> Day14.frequencies()
76
+
|> Enum.min_max_by(&elem(&1, 1))
77
+
78
+
# 2768
79
+
max - min
80
+
```
81
+
82
+
```output
83
+
2768
84
+
```
85
+
86
+
## Task 2
87
+
88
+
```elixir
89
+
{{_, min}, {_, max}} =
90
+
1..40
91
+
|> Enum.reduce(polymer, fn _, acc ->
92
+
Day14.expand(acc, subs)
93
+
end)
94
+
|> Day14.frequencies()
95
+
|> Enum.min_max_by(&elem(&1, 1))
96
+
97
+
max - min
98
+
```
99
+
100
+
```output
101
+
2914365137499
102
+
```
+117
2021/day15.livemd
+117
2021/day15.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 15
7
+
8
+
```elixir
9
+
input =
10
+
File.read!("day15.txt")
11
+
|> String.trim()
12
+
|> String.split("\n")
13
+
|> Enum.map(&String.to_charlist/1)
14
+
|> Enum.with_index()
15
+
|> Enum.flat_map(fn {row, y} ->
16
+
row
17
+
|> Enum.with_index()
18
+
|> Enum.map(fn {v, x} -> {{x, y}, v - ?0} end)
19
+
end)
20
+
|> Map.new()
21
+
22
+
{width, height} = Enum.max(Map.keys(input))
23
+
```
24
+
25
+
```output
26
+
{99, 99}
27
+
```
28
+
29
+
## Task 1
30
+
31
+
```elixir
32
+
shortest_paths =
33
+
for y <- height..0//-1,
34
+
x <- width..0//-1,
35
+
reduce: %{} do
36
+
acc ->
37
+
right = acc[{x + 1, y}]
38
+
bottom = acc[{x, y + 1}]
39
+
40
+
value =
41
+
case {right, bottom} do
42
+
{nil, nil} -> input[{x, y}]
43
+
_ -> input[{x, y}] + min(right, bottom)
44
+
end
45
+
46
+
Map.put(acc, {x, y}, value)
47
+
end
48
+
49
+
shortest_paths[{0, 0}] - input[{0, 0}]
50
+
```
51
+
52
+
```output
53
+
429
54
+
```
55
+
56
+
## Task 2
57
+
58
+
```elixir
59
+
defmodule Day15.Task2 do
60
+
def expand_grid(board) do
61
+
{width, height} = Enum.max(Map.keys(board))
62
+
63
+
board
64
+
|> Enum.flat_map(fn {{x, y}, v} ->
65
+
for rx <- 0..4, ry <- 0..4 do
66
+
{{x + (width + 1) * rx, y + (height + 1) * ry}, rem(v - 1 + rx + ry, 9) + 1}
67
+
end
68
+
end)
69
+
|> Map.new()
70
+
end
71
+
72
+
def find_path(board, start, finish) do
73
+
dists = :gb_sets.singleton({0, start})
74
+
75
+
find_path(board, finish, dists, MapSet.new())
76
+
end
77
+
78
+
@surround for dx <- -1..1, dy <- -1..1, abs(dx) != abs(dy), do: {dx, dy}
79
+
80
+
def find_path(board, finish, dists, visited) do
81
+
{{dist, {x, y} = curr}, dists} = :gb_sets.take_smallest(dists)
82
+
83
+
if curr == finish do
84
+
dist
85
+
else
86
+
visited = MapSet.put(visited, curr)
87
+
88
+
dists =
89
+
for {dx, dy} <- @surround,
90
+
next = {x + dx, y + dy},
91
+
next not in visited,
92
+
is_map_key(board, next),
93
+
alt = dist + board[next],
94
+
reduce: dists do
95
+
acc ->
96
+
:gb_sets.add_element({alt, next}, acc)
97
+
end
98
+
99
+
find_path(board, finish, dists, visited)
100
+
end
101
+
end
102
+
end
103
+
```
104
+
105
+
```output
106
+
{:module, Day15.Task2, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:find_path, 4}}
107
+
```
108
+
109
+
```elixir
110
+
input
111
+
|> Day15.Task2.expand_grid()
112
+
|> Day15.Task2.find_path({0, 0}, {499, 499})
113
+
```
114
+
115
+
```output
116
+
2844
117
+
```
+610
2021/day16.livemd
+610
2021/day16.livemd
···
1
+
<!-- vim:ft=markdown -->
2
+
3
+
<!-- livebook:{"persist_outputs":true} -->
4
+
5
+
# Day 16
6
+
7
+
## Section
8
+
9
+
```elixir
10
+
defmodule Day16 do
11
+
defmodule Packet do
12
+
defstruct [:version, :type, :value]
13
+
end
14
+
15
+
def decode(<<version::3, 4::3, rest::bitstring>>) do
16
+
{value, rest} = literal(rest, 0)
17
+
18
+
{%Packet{type: 4, version: version, value: value}, rest}
19
+
end
20
+
21
+
def decode(<<version::3, type::3, 0::1, length::15, rest::bitstring>>) do
22
+
<<subpackets::bitstring-size(length), rest::bitstring>> = rest
23
+
24
+
{%Packet{type: type, version: version, value: decode_all(subpackets)}, rest}
25
+
end
26
+
27
+
def decode(<<version::3, type::3, 1::1, length::11, rest::bitstring>>) do
28
+
{value, rest} = Enum.map_reduce(1..length, rest, fn _, acc -> decode(acc) end)
29
+
30
+
{%Packet{type: type, version: version, value: value}, rest}
31
+
end
32
+
33
+
def decode_all(input) do
34
+
case decode(input) do
35
+
{packet, <<>>} -> [packet]
36
+
{packet, rest} -> [packet | decode_all(rest)]
37
+
end
38
+
end
39
+
40
+
defp literal(<<1::1, bits::4, rest::bitstring>>, acc) do
41
+
literal(rest, acc * 0x10 + bits)
42
+
end
43
+
44
+
defp literal(<<0::1, bits::4, rest::bitstring>>, acc) do
45
+
{acc * 0x10 + bits, rest}
46
+
end
47
+
end
48
+
49
+
input =
50
+
File.read!("day16.txt")
51
+
|> String.trim()
52
+
|> Base.decode16!()
53
+
|> Day16.decode()
54
+
|> elem(0)
55
+
```
56
+
57
+
```output
58
+
%Day16.Packet{
59
+
type: 0,
60
+
value: [
61
+
%Day16.Packet{
62
+
type: 1,
63
+
value: [
64
+
%Day16.Packet{type: 4, value: 20, version: 6},
65
+
%Day16.Packet{
66
+
type: 6,
67
+
value: [
68
+
%Day16.Packet{type: 4, value: 14747, version: 1},
69
+
%Day16.Packet{type: 4, value: 14747, version: 6}
70
+
],
71
+
version: 2
72
+
}
73
+
],
74
+
version: 1
75
+
},
76
+
%Day16.Packet{
77
+
type: 3,
78
+
value: [
79
+
%Day16.Packet{type: 4, value: 15, version: 5},
80
+
%Day16.Packet{type: 4, value: 10, version: 6}
81
+
],
82
+
version: 7
83
+
},
84
+
%Day16.Packet{
85
+
type: 1,
86
+
value: [
87
+
%Day16.Packet{
88
+
type: 7,
89
+
value: [
90
+
%Day16.Packet{type: 4, value: 2184, version: 1},
91
+
%Day16.Packet{type: 4, value: 130250, version: 6}
92
+
],
93
+
version: 6
94
+
},
95
+
%Day16.Packet{type: 4, value: 5442981, version: 4}
96
+
],
97
+
version: 6
98
+
},
99
+
%Day16.Packet{type: 4, value: 8281083, version: 0},
100
+
%Day16.Packet{
101
+
type: 2,
102
+
value: [
103
+
%Day16.Packet{type: 4, value: 102, version: 5},
104
+
%Day16.Packet{type: 4, value: 647125, version: 7}
105
+
],
106
+
version: 1
107
+
},
108
+
%Day16.Packet{
109
+
type: 1,
110
+
value: [
111
+
%Day16.Packet{type: 4, value: 178, version: 1},
112
+
%Day16.Packet{type: 4, value: 176, version: 6}
113
+
],
114
+
version: 0
115
+
},
116
+
%Day16.Packet{
117
+
type: 1,
118
+
value: [
119
+
%Day16.Packet{
120
+
type: 6,
121
+
value: [
122
+
%Day16.Packet{
123
+
type: 0,
124
+
value: [
125
+
%Day16.Packet{type: 4, value: 13, version: 1},
126
+
%Day16.Packet{type: 4, value: 8, version: 4},
127
+
%Day16.Packet{type: 4, value: 4, version: 3}
128
+
],
129
+
version: 2
130
+
},
131
+
%Day16.Packet{
132
+
type: 0,
133
+
value: [
134
+
%Day16.Packet{type: 4, value: 7, version: 7},
135
+
%Day16.Packet{type: 4, value: 11, version: 3},
136
+
%Day16.Packet{type: 4, value: 14, version: 2}
137
+
],
138
+
version: 4
139
+
}
140
+
],
141
+
version: 7
142
+
},
143
+
%Day16.Packet{type: 4, value: 2724, version: 0}
144
+
],
145
+
version: 1
146
+
},
147
+
%Day16.Packet{type: 4, value: 9, version: 4},
148
+
%Day16.Packet{
149
+
type: 1,
150
+
value: [
151
+
%Day16.Packet{
152
+
type: 5,
153
+
value: [
154
+
%Day16.Packet{type: 4, value: 7240238, version: 2},
155
+
%Day16.Packet{type: 4, value: 233, version: 7}
156
+
],
157
+
version: 1
158
+
},
159
+
%Day16.Packet{type: 4, value: 37, version: 6}
160
+
],
161
+
version: 4
162
+
},
163
+
%Day16.Packet{type: 2, value: [%Day16.Packet{type: 4, value: 2, version: 5}], version: 5},
164
+
%Day16.Packet{type: 4, value: 53749, version: 4},
165
+
%Day16.Packet{type: 4, value: 11, version: 3},
166
+
%Day16.Packet{
167
+
type: 1,
168
+
value: [
169
+
%Day16.Packet{type: 4, value: 382979, version: 4},
170
+
%Day16.Packet{
171
+
type: 5,
172
+
value: [
173
+
%Day16.Packet{
174
+
type: 0,
175
+
value: [
176
+
%Day16.Packet{type: 4, value: 15, version: 1},
177
+
%Day16.Packet{type: 4, value: 10, version: 0},
178
+
%Day16.Packet{type: 4, value: 2, version: 6}
179
+
],
180
+
version: 5
181
+
},
182
+
%Day16.Packet{
183
+
type: 0,
184
+
value: [
185
+
%Day16.Packet{type: 4, value: 4, version: 7},
186
+
%Day16.Packet{type: 4, value: 7, version: 4},
187
+
%Day16.Packet{type: 4, value: 2, version: 5}
188
+
],
189
+
version: 1
190
+
}
191
+
],
192
+
version: 6
193
+
}
194
+
],
195
+
version: 2
196
+
},
197
+
%Day16.Packet{type: 4, value: 21251, version: 1},
198
+
%Day16.Packet{
199
+
type: 1,
200
+
value: [
201
+
%Day16.Packet{type: 4, value: 163, version: 6},
202
+
%Day16.Packet{
203
+
type: 5,
204
+
value: [
205
+
%Day16.Packet{type: 4, value: 59, version: 3},
206
+
%Day16.Packet{type: 4, value: 836848134220, version: 1}
207
+
],
208
+
version: 6
209
+
}
210
+
],
211
+
version: 2
212
+
},
213
+
%Day16.Packet{
214
+
type: 2,
215
+
value: [
216
+
%Day16.Packet{
217
+
type: 0,
218
+
value: [
219
+
%Day16.Packet{
220
+
type: 0,
221
+
value: [
222
+
%Day16.Packet{
223
+
type: 2,
224
+
value: [
225
+
%Day16.Packet{
226
+
type: 2,
227
+
value: [
228
+
%Day16.Packet{
229
+
type: 0,
230
+
value: [
231
+
%Day16.Packet{
232
+
type: 3,
233
+
value: [
234
+
%Day16.Packet{
235
+
type: 2,
236
+
value: [
237
+
%Day16.Packet{
238
+
type: 2,
239
+
value: [
240
+
%Day16.Packet{
241
+
type: 3,
242
+
value: [%Day16.Packet{type: 0, value: [...], ...}],
243
+
version: 0
244
+
}
245
+
],
246
+
version: 1
247
+
}
248
+
],
249
+
version: 1
250
+
}
251
+
],
252
+
version: 7
253
+
}
254
+
],
255
+
version: 0
256
+
}
257
+
],
258
+
version: 6
259
+
}
260
+
],
261
+
version: 2
262
+
}
263
+
],
264
+
version: 2
265
+
}
266
+
],
267
+
version: 6
268
+
}
269
+
],
270
+
version: 7
271
+
},
272
+
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 4, value: 44, version: 4}], version: 7},
273
+
%Day16.Packet{
274
+
type: 1,
275
+
value: [
276
+
%Day16.Packet{type: 4, value: 255, version: 2},
277
+
%Day16.Packet{type: 4, value: 91, version: 5},
278
+
%Day16.Packet{type: 4, value: 176, version: 5},
279
+
%Day16.Packet{type: 4, value: 23, version: 1}
280
+
],
281
+
version: 7
282
+
},
283
+
%Day16.Packet{
284
+
type: 3,
285
+
value: [
286
+
%Day16.Packet{type: 4, value: 11520, version: 4},
287
+
%Day16.Packet{type: 4, value: 6069, version: 0},
288
+
%Day16.Packet{type: 4, value: 1089149511401, version: 4},
289
+
%Day16.Packet{type: 4, value: 158, version: 2},
290
+
%Day16.Packet{type: 4, value: 620605, version: 0}
291
+
],
292
+
version: 2
293
+
},
294
+
%Day16.Packet{
295
+
type: 0,
296
+
value: [
297
+
%Day16.Packet{type: 4, value: 62788, version: 7},
298
+
%Day16.Packet{type: 4, value: 9410622, version: 2},
299
+
%Day16.Packet{type: 4, value: 15912821, version: 4}
300
+
],
301
+
version: 4
302
+
},
303
+
%Day16.Packet{
304
+
type: 1,
305
+
value: [
306
+
%Day16.Packet{type: 4, value: 22416, version: 5},
307
+
%Day16.Packet{
308
+
type: 5,
309
+
value: [
310
+
%Day16.Packet{type: 4, value: 246, version: 1},
311
+
%Day16.Packet{type: 4, value: 246, version: 4}
312
+
],
313
+
version: 2
314
+
}
315
+
],
316
+
version: 0
317
+
},
318
+
%Day16.Packet{type: 3, value: [%Day16.Packet{type: 4, value: 13008601, version: 5}], version: 0},
319
+
%Day16.Packet{
320
+
type: 0,
321
+
value: [
322
+
%Day16.Packet{
323
+
type: 1,
324
+
value: [
325
+
%Day16.Packet{type: 4, value: 3, version: 4},
326
+
%Day16.Packet{type: 4, value: 14, version: 1},
327
+
%Day16.Packet{type: 4, value: 5, version: 0}
328
+
],
329
+
version: 5
330
+
},
331
+
%Day16.Packet{
332
+
type: 1,
333
+
value: [
334
+
%Day16.Packet{type: 4, value: 2, version: 1},
335
+
%Day16.Packet{type: 4, value: 14, version: 1},
336
+
%Day16.Packet{type: 4, value: 10, version: 1}
337
+
],
338
+
version: 6
339
+
},
340
+
%Day16.Packet{
341
+
type: 1,
342
+
value: [
343
+
%Day16.Packet{type: 4, value: 8, version: 3},
344
+
%Day16.Packet{type: 4, value: 6, version: 6},
345
+
%Day16.Packet{type: 4, value: 11, version: 0}
346
+
],
347
+
version: 1
348
+
}
349
+
],
350
+
version: 5
351
+
},
352
+
%Day16.Packet{
353
+
type: 1,
354
+
value: [
355
+
%Day16.Packet{type: 4, value: 32940592237, version: 2},
356
+
%Day16.Packet{
357
+
type: 5,
358
+
value: [
359
+
%Day16.Packet{type: 4, value: 100, version: 1},
360
+
%Day16.Packet{type: 4, value: 1393232728, version: 2}
361
+
],
362
+
version: 2
363
+
}
364
+
],
365
+
version: 0
366
+
},
367
+
%Day16.Packet{type: 4, value: 89, version: 3},
368
+
%Day16.Packet{
369
+
type: 2,
370
+
value: [
371
+
%Day16.Packet{type: 4, value: 204, version: 6},
372
+
%Day16.Packet{type: 4, value: 260321821, version: 2},
373
+
%Day16.Packet{type: 4, value: 225241983, version: 6}
374
+
],
375
+
version: 0
376
+
},
377
+
%Day16.Packet{
378
+
type: 0,
379
+
value: [
380
+
%Day16.Packet{type: 4, value: 960899, version: 3},
381
+
%Day16.Packet{type: 4, value: 58997, version: 5},
382
+
%Day16.Packet{type: 4, value: 54940, version: 6},
383
+
%Day16.Packet{type: 4, value: 10974, version: 2},
384
+
%Day16.Packet{type: 4, value: 882043, version: 2}
385
+
],
386
+
version: 0
387
+
},
388
+
%Day16.Packet{
389
+
type: 1,
390
+
value: [
391
+
%Day16.Packet{
392
+
type: 6,
393
+
value: [
394
+
%Day16.Packet{type: 4, value: 35633017255, version: 4},
395
+
%Day16.Packet{type: 4, value: 35633017255, version: 2}
396
+
],
397
+
version: 3
398
+
},
399
+
%Day16.Packet{type: 4, value: 1359, version: 6}
400
+
],
401
+
version: 6
402
+
},
403
+
%Day16.Packet{
404
+
type: 1,
405
+
value: [
406
+
%Day16.Packet{type: 4, value: 92, version: 4},
407
+
%Day16.Packet{type: 4, value: 38, version: 3},
408
+
%Day16.Packet{type: 4, value: 160, version: 5},
409
+
%Day16.Packet{type: 4, value: 111, version: 1},
410
+
%Day16.Packet{type: 4, value: 64, version: 4}
411
+
],
412
+
version: 4
413
+
},
414
+
%Day16.Packet{
415
+
type: 0,
416
+
value: [
417
+
%Day16.Packet{type: 4, value: 2541, version: 3},
418
+
%Day16.Packet{type: 4, value: 263947, version: 6},
419
+
%Day16.Packet{type: 4, value: 7686705, version: 5},
420
+
%Day16.Packet{type: 4, value: 31, version: 4}
421
+
],
422
+
version: 2
423
+
},
424
+
%Day16.Packet{
425
+
type: 1,
426
+
value: [
427
+
%Day16.Packet{
428
+
type: 6,
429
+
value: [
430
+
%Day16.Packet{type: 4, value: 3193865, version: 1},
431
+
%Day16.Packet{type: 4, value: 20223, version: 7}
432
+
],
433
+
version: 2
434
+
},
435
+
%Day16.Packet{type: 4, value: 9328522, version: 5}
436
+
],
437
+
version: 0
438
+
},
439
+
%Day16.Packet{
440
+
type: 2,
441
+
value: [
442
+
%Day16.Packet{type: 4, value: 5, version: 4},
443
+
%Day16.Packet{type: 4, value: 7, version: 3},
444
+
%Day16.Packet{type: 4, value: 179420284, version: 4},
445
+
%Day16.Packet{type: 4, value: 19890, version: 1},
446
+
%Day16.Packet{type: 4, value: 2655, version: 0}
447
+
],
448
+
version: 7
449
+
},
450
+
%Day16.Packet{
451
+
type: 1,
452
+
value: [
453
+
%Day16.Packet{type: 4, value: 862089, version: 1},
454
+
%Day16.Packet{
455
+
type: 6,
456
+
value: [
457
+
%Day16.Packet{type: 4, value: 248, version: 3},
458
+
%Day16.Packet{type: 4, value: 3286, version: 5}
459
+
],
460
+
version: 3
461
+
}
462
+
],
463
+
version: 3
464
+
},
465
+
%Day16.Packet{
466
+
type: 1,
467
+
value: [
468
+
%Day16.Packet{type: 4, value: 93, version: 6},
469
+
%Day16.Packet{
470
+
type: 5,
471
+
value: [
472
+
%Day16.Packet{type: 4, value: 4269, version: 6},
473
+
%Day16.Packet{type: 4, value: 240, version: 3}
474
+
],
475
+
version: 4
476
+
}
477
+
],
478
+
version: 5
479
+
},
480
+
%Day16.Packet{
481
+
type: 3,
482
+
value: [
483
+
%Day16.Packet{type: 4, value: 2938, version: 6},
484
+
%Day16.Packet{type: 4, value: 3, version: 6},
485
+
%Day16.Packet{type: 4, value: 211, version: 7}
486
+
],
487
+
version: 3
488
+
},
489
+
%Day16.Packet{
490
+
type: 1,
491
+
value: [
492
+
%Day16.Packet{
493
+
type: 7,
494
+
value: [
495
+
%Day16.Packet{type: 4, value: 159, version: 0},
496
+
%Day16.Packet{type: 4, value: 159, version: 5}
497
+
],
498
+
version: 0
499
+
},
500
+
%Day16.Packet{type: 4, value: 28, version: 1}
501
+
],
502
+
version: 4
503
+
},
504
+
%Day16.Packet{type: 4, value: 84, version: 4},
505
+
%Day16.Packet{
506
+
type: 1,
507
+
value: [
508
+
%Day16.Packet{type: 4, value: 235, version: 4},
509
+
%Day16.Packet{
510
+
type: 6,
511
+
value: [
512
+
%Day16.Packet{type: 0, value: [%Day16.Packet{...}, ...], version: 4},
513
+
%Day16.Packet{type: 0, value: [...], ...}
514
+
],
515
+
version: 3
516
+
}
517
+
],
518
+
version: 6
519
+
},
520
+
%Day16.Packet{type: 4, value: 1425, version: 4},
521
+
%Day16.Packet{
522
+
type: 1,
523
+
value: [
524
+
%Day16.Packet{
525
+
type: 7,
526
+
value: [%Day16.Packet{type: 0, value: [...], ...}, %Day16.Packet{type: 0, ...}],
527
+
version: 5
528
+
},
529
+
%Day16.Packet{type: 4, value: 13, version: 2}
530
+
],
531
+
version: 2
532
+
},
533
+
%Day16.Packet{type: 0, value: [%Day16.Packet{type: 4, value: 3121, version: 6}], version: 5},
534
+
%Day16.Packet{
535
+
type: 1,
536
+
value: [
537
+
%Day16.Packet{type: 4, value: 51, version: 2},
538
+
%Day16.Packet{type: 4, value: 61, ...},
539
+
%Day16.Packet{type: 4, ...}
540
+
],
541
+
version: 4
542
+
},
543
+
%Day16.Packet{
544
+
type: 1,
545
+
value: [%Day16.Packet{type: 4, value: 1393, ...}, %Day16.Packet{type: 5, ...}],
546
+
version: 3
547
+
},
548
+
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 7, ...}, %Day16.Packet{...}], version: 3},
549
+
%Day16.Packet{type: 1, value: [%Day16.Packet{...}, ...], version: 7},
550
+
%Day16.Packet{type: 3, value: [...], ...},
551
+
%Day16.Packet{type: 2, ...},
552
+
%Day16.Packet{...},
553
+
...
554
+
],
555
+
version: 3
556
+
}
557
+
```
558
+
559
+
## Task 1
560
+
561
+
```elixir
562
+
defmodule Day16.Task1 do
563
+
alias Day16.Packet
564
+
565
+
def sum(%Packet{type: 4, version: version}), do: version
566
+
567
+
def sum(%Packet{version: version, value: value}) do
568
+
Enum.reduce(value, version, &(sum(&1) + &2))
569
+
end
570
+
end
571
+
572
+
Day16.Task1.sum(input)
573
+
```
574
+
575
+
```output
576
+
949
577
+
```
578
+
579
+
## Task 2
580
+
581
+
```elixir
582
+
defmodule Day16.Task2 do
583
+
alias Day16.Packet
584
+
585
+
def evaluate(%Packet{type: 0} = packet), do: reduce(packet, 0, &+/2)
586
+
def evaluate(%Packet{type: 1} = packet), do: reduce(packet, 1, &*/2)
587
+
def evaluate(%Packet{type: 2} = packet), do: reduce(packet, :inf, &min/2)
588
+
def evaluate(%Packet{type: 3} = packet), do: reduce(packet, 0, &max/2)
589
+
590
+
def evaluate(%Packet{type: 4, value: value}), do: value
591
+
592
+
def evaluate(%Packet{type: 5} = packet), do: compare(packet, &>/2)
593
+
def evaluate(%Packet{type: 6} = packet), do: compare(packet, &</2)
594
+
def evaluate(%Packet{type: 7} = packet), do: compare(packet, &==/2)
595
+
596
+
defp reduce(%Packet{value: value}, initial, op) do
597
+
Enum.reduce(value, initial, &op.(evaluate(&1), &2))
598
+
end
599
+
600
+
defp compare(%Packet{value: [a, b]}, op) do
601
+
if op.(evaluate(a), evaluate(b)), do: 1, else: 0
602
+
end
603
+
end
604
+
605
+
Day16.Task2.evaluate(input)
606
+
```
607
+
608
+
```output
609
+
1114600142730
610
+
```
+185
2021/day17.livemd
+185
2021/day17.livemd
···
1
+
<!-- vim:ft=markdown -->
2
+
3
+
<!-- livebook:{"persist_outputs":true} -->
4
+
5
+
# Day 17
6
+
7
+
## Setup
8
+
9
+
```elixir
10
+
input = File.read!("day17.txt")
11
+
# input = "target area: x=117..7310, y=-9546..-89"
12
+
13
+
IO.puts(input)
14
+
15
+
%{"a_x" => a_x, "a_y" => a_y, "b_x" => b_x, "b_y" => b_y} =
16
+
Regex.named_captures(
17
+
~r/target area: x=(?<a_x>-?\d+)\.\.(?<b_x>-?\d+), y=(?<a_y>-?\d+)\.\.(?<b_y>-?\d+)/,
18
+
input
19
+
)
20
+
21
+
a = %{x: String.to_integer(a_x), y: String.to_integer(a_y)}
22
+
b = %{x: String.to_integer(b_x), y: String.to_integer(b_y)}
23
+
24
+
[a: a, b: b]
25
+
```
26
+
27
+
```output
28
+
target area: x=288..330, y=-96..-50
29
+
```
30
+
31
+
```output
32
+
[a: %{x: 288, y: -96}, b: %{x: 330, y: -50}]
33
+
```
34
+
35
+
## Task 1
36
+
37
+
### Lemma 1
38
+
39
+
The horizontal velocity there can be ignored, as we can always find a horizontal velocity
40
+
that will reach the target area and will reduce the velocity to $$0$$, which mean that all
41
+
further movement will happen only in one dimension. That velocity is:
42
+
43
+
$$
44
+
v_x = \lceil \frac{-1 + \sqrt{1 + 8b_x}}{2} \rceil
45
+
$$
46
+
47
+
#### Proof:
48
+
49
+
Which came from the fact that distance traveled by the projectile is sum of the arithmetic
50
+
sequence with $$r = -1$$, so the distance traveled is:
51
+
52
+
$$
53
+
s_x = \frac{2v_{x0} - t + 1}{2}t
54
+
$$
55
+
56
+
Where $$t$$ is travel time. As $$v_x(t) = v_{x0}$$ then $$v_x(t) = 0 \implies t = v_{x0}$$,
57
+
so after substituting $$t$$ we get:
58
+
59
+
$$
60
+
s_x = \frac{2v_{x0} - v_{x0} + 1}{2}v_{x0} \\
61
+
s_x = \frac{v_{x0} + 1}{2}v_{x0} \\
62
+
s_x = \frac{v_{x0}^2 + v_{x0}}{2}
63
+
$$
64
+
65
+
As we want to find the nearest column where we want to stop movement in $$OX$$ then
66
+
we are looking at $$s_x = b_x$$:
67
+
68
+
$$
69
+
b_x = \frac{v_{x0}^2 + v_{x0}}{2} \\
70
+
2b_x = v_{x0}^2 + v_{x0} \\
71
+
0 = v_{x0}^2 + v_{x0} - 2b_x
72
+
$$
73
+
74
+
The soultions for these equation are in form of:
75
+
76
+
$$
77
+
v_{x0} = \frac{-1 \mp \sqrt{1 + 8b_x}}{2}
78
+
$$
79
+
80
+
As we assume that $$b_x \gt 0$$, then the solutions will always be trivial. Additionally
81
+
we do not care about negative roots, so we can take only:
82
+
83
+
$$
84
+
v_{x0} = \frac{-1 + \sqrt{1 + 8b_x}}{2}
85
+
$$
86
+
87
+
As this can be fractional and we want $$v_x0 \in \mathbb{Z}$$ and assume that target is
88
+
big enough to have at least one point that we can land on, then we can simply round velocity
89
+
up:
90
+
91
+
$$
92
+
v_x = \lceil \frac{-1 + \sqrt{1 + 8b_x}}{2} \rceil\\
93
+
$$
94
+
95
+
$$\blacksquare$$
96
+
97
+
### Lemma 2
98
+
99
+
TODO
100
+
101
+
As
102
+
103
+
$$
104
+
v_{y0} = \frac{2a_y - t + t^2}{2t}
105
+
$$
106
+
107
+
Left to prove that $$v_0$$ will have highest possible value for $$t = -2a_y$$.
108
+
Then above equation reduces like that:
109
+
110
+
$$
111
+
v_{y0} = \frac{2a_y + 2a_y + 4a_y^2}{4a_y} \\
112
+
v_{y0} = \frac{4a_y + 4a_y^2}{4a_y} \\
113
+
v_{y0} = 1 + a_y
114
+
$$
115
+
116
+
```elixir
117
+
v_y = -min(a.y, b.y) - 1
118
+
119
+
{v_y, v_y * (v_y + 1) / 2}
120
+
```
121
+
122
+
```output
123
+
{95, 4560.0}
124
+
```
125
+
126
+
## Task 2
127
+
128
+
```elixir
129
+
solveq_pos = fn a, b, c ->
130
+
[
131
+
(-b - :math.sqrt(b * b - 4 * a * c)) / (2 * a),
132
+
(-b + :math.sqrt(b * b - 4 * a * c)) / (2 * a)
133
+
]
134
+
|> Enum.filter(&(&1 > 0))
135
+
end
136
+
137
+
v_xmin_rest = ceil(hd(solveq_pos.(1, 1, -2 * min(a.x, b.x))))
138
+
v_xmax_rest = floor(hd(solveq_pos.(1, 1, -2 * max(a.x, b.x))))
139
+
140
+
v_ymax = -min(a.y, b.y) - 1
141
+
v_ymin = min(a.y, b.y)
142
+
143
+
{xmin, xmax} = Enum.min_max([a.x, b.x])
144
+
{ymin, ymax} = Enum.min_max([a.y, b.y])
145
+
146
+
offset = fn
147
+
0 -> {1, -1}
148
+
v_y when v_y > 0 -> {2 * v_y + 1, -v_y - 1}
149
+
v_y -> {0, v_y}
150
+
end
151
+
152
+
v_y_pairs =
153
+
for v_y <- v_ymin..v_ymax,
154
+
{offset, fv_y} = offset.(v_y),
155
+
tmin <- solveq_pos.(-1, 2 * fv_y + 1, -2 * ymax),
156
+
tmax <- solveq_pos.(-1, 2 * fv_y + 1, -2 * ymin),
157
+
ceil(tmin) <= floor(tmax),
158
+
t <- ceil(tmin)..floor(tmax),
159
+
do: {v_y, t + offset}
160
+
161
+
v_x_pairs =
162
+
for t <- Enum.uniq(Enum.map(v_y_pairs, &elem(&1, 1))),
163
+
v_xmin_move = ceil((2 * xmin / t + t - 1) / 2),
164
+
v_xmax_move = floor((2 * xmax / t + t - 1) / 2),
165
+
xrange = Enum.filter(v_xmin_move..v_xmax_move, &(&1 >= t)),
166
+
xrange =
167
+
if(v_xmin_rest < t,
168
+
do: Enum.concat(xrange, v_xmin_rest..min(t, v_xmax_rest)),
169
+
else: xrange
170
+
),
171
+
v_x <- MapSet.new(xrange),
172
+
do: {t, v_x}
173
+
174
+
pairs =
175
+
for {v_y, t} <- v_y_pairs,
176
+
{^t, v_x} <- v_x_pairs,
177
+
into: MapSet.new(),
178
+
do: {v_x, v_y}
179
+
180
+
MapSet.size(pairs)
181
+
```
182
+
183
+
```output
184
+
3344
185
+
```
+1
2021/day17.txt
+1
2021/day17.txt
···
1
+
target area: x=288..330, y=-96..-50
+172
2021/day18.livemd
+172
2021/day18.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 18
4
+
5
+
## Input
6
+
7
+
```elixir
8
+
input =
9
+
File.stream!("day18.txt")
10
+
|> Enum.map(&elem(Code.eval_string(&1), 0))
11
+
```
12
+
13
+
```output
14
+
[
15
+
[[[6, [8, 3]], [2, 0]], [[[9, 5], [9, 1]], 3]],
16
+
[[[9, [2, 2]], [5, 4]], [[[2, 2], [9, 6]], '\a\a']],
17
+
[[[0, [3, 2]], 1], [[0, [2, 8]], [2, [0, 4]]]],
18
+
[[4, 4], [[[7, 0], 5], [3, 1]]],
19
+
[[5, 4], 1],
20
+
[[[[7, 6], 4], 9], [[9, 1], 9]],
21
+
[[[1, '\a\b'], ['\a\a', [1, 6]]], [1, [6, [7, 1]]]],
22
+
[[[[6, 8], [5, 6]], [[1, 1], 8]], [[[2, 0], [3, 1]], [2, [2, 6]]]],
23
+
[[[6, 3], [3, [7, 1]]], 8],
24
+
[[[9, 4], [3, [0, 6]]], [[2, [3, 6]], ['\t\b', [1, 6]]]],
25
+
[9, [0, [[0, 7], 2]]],
26
+
[[[[8, 4], 7], [[9, 2], [0, 9]]], ['\a\t', [8, [0, 9]]]],
27
+
[[1, 1], [[5, [3, 8]], [3, [4, 7]]]],
28
+
[[[9, [2, 9]], [2, [2, 9]]], [[[3, 5], 5], [[3, 3], 2]]],
29
+
[[[[5, 4], 9], 0], [[[5, 7], 2], [[5, 2], 9]]],
30
+
[[2, [[1, 0], [6, 2]]], 0],
31
+
[[[3, 7], [7, 6]], [[[2, 8], 5], [3, '\t\a']]],
32
+
[[2, [2, '\b\b']], [['\t\t', [1, 1]], [[8, 6], [0, 3]]]],
33
+
[[8, 1], [3, 5]],
34
+
[[7, [[7, 6], [2, 0]]], 4],
35
+
[[5, 4], [[1, 3], [5, [2, 8]]]],
36
+
'\a\t',
37
+
[[[[6, 9], 0], [1, [5, 0]]], [[[6, 4], 3], 7]],
38
+
[[[[3, 7], 3], [2, 6]], [[0, 4], '\t\t']],
39
+
[[[[1, 5], [5, 0]], [9, 4]], [[[8, 3], 3], [8, [3, 6]]]],
40
+
[[[[3, 7], 5], [[8, 5], [1, 5]]], [[0, 6], [3, 4]]],
41
+
[[[[4, 0], 2], [7, [8, 4]]], [0, [5, '\a\b']]],
42
+
[[[[0, 8], [0, 4]], [9, 3]], [[[5, 4], [4, 8]], [[1, 6], [5, 4]]]],
43
+
[[0, [0, 3]], [[3, [1, 5]], [[9, 6], [0, 6]]]],
44
+
[[9, [8, 4]], [7, 1]],
45
+
[[[[1, 9], '\a\a'], 9], [[6, [4, 5]], [8, [3, 2]]]],
46
+
[5, [[2, [9, 5]], [3, [4, 0]]]],
47
+
[[[6, 2], [[1, 8], 5]], 6],
48
+
[[8, [6, [6, 4]]], [0, ['\t\b', 7]]],
49
+
[[[[6, 3], [8, 0]], [8, [2, 7]]], 8],
50
+
[[[6, [3, 6]], [[4, 0], [4, 7]]], [0, [[4, 0], [4, 5]]]],
51
+
[[[3, [8, 1]], 1], [2, 3]],
52
+
[[[6, [7, 0]], [[3, 5], [3, 4]]], 7],
53
+
[[[[8, 0], 3], 8], [[[1, 6], 3], [[0, 5], 2]]],
54
+
[[[3, 7], ['\t\b', 8]], [[[8, 4], 7], [3, [1, 7]]]],
55
+
[[[0, 5], [[5, 5], '\a\b']], [9, [5, [2, 2]]]],
56
+
[[2, 9], [[[7, 4], 4], [[8, 0], [6, 9]]]],
57
+
[[['\a\b', '\b\b'], 0], 9],
58
+
[[[4, [0, 6]], [[5, 9], [0, ...]]], [3, [6, 7]]],
59
+
[[[7, [6, ...]], [5, [...]]], [[[3, ...], 6], [[...], ...]]],
60
+
[3, [[[...], ...], [...]]],
61
+
[[[3, ...], [...]], [[...], ...]],
62
+
[['\t\a', ...], [...]],
63
+
[[...], ...],
64
+
[...],
65
+
...
66
+
]
67
+
```
68
+
69
+
```elixir
70
+
defmodule Day18 do
71
+
def add(a, b) do
72
+
sum = reduce([a, b])
73
+
74
+
# IO.puts("""
75
+
# #{inspect(a, charlists: :as_list)}
76
+
# + #{inspect(b, charlists: :as_list)}
77
+
# = #{inspect(sum, charlists: :as_list)}
78
+
# """)
79
+
80
+
sum
81
+
end
82
+
83
+
defp reduce(list) do
84
+
# First try to explode
85
+
# If that returned list in the same form, then try to split it
86
+
# If all above returned input list, then we have reached fixed point
87
+
with ^list <- explode(list),
88
+
^list <- split(list) do
89
+
list
90
+
else
91
+
new_list -> reduce(new_list)
92
+
end
93
+
end
94
+
95
+
defp explode(list) do
96
+
{_, _, exploded} = explode(list, 0)
97
+
98
+
exploded
99
+
end
100
+
101
+
defp explode(num, _) when is_number(num), do: {0, 0, num}
102
+
103
+
defp explode([a, b], 4), do: {a, b, 0}
104
+
105
+
defp explode([a, b], n) do
106
+
{la, ra, na} = explode(a, n + 1)
107
+
{lb, rb, nb} = explode(explode_add(ra, b), n + 1)
108
+
109
+
{la, rb, [explode_add(na, lb), nb]}
110
+
end
111
+
112
+
defp explode_add([a, b], v), do: [a, explode_add(b, v)]
113
+
defp explode_add(v, [a, b]), do: [explode_add(v, a), b]
114
+
defp explode_add(a, b), do: a + b
115
+
116
+
defp split(n) when n in 0..9, do: n
117
+
defp split(n) when is_integer(n), do: [div(n, 2), div(n + 1, 2)]
118
+
119
+
defp split([a, b]) do
120
+
with {:a, ^a} <- {:a, split(a)},
121
+
{:b, ^b} <- {:b, split(b)} do
122
+
[a, b]
123
+
else
124
+
{:a, mod} -> [mod, b]
125
+
{:b, mod} -> [a, mod]
126
+
end
127
+
end
128
+
129
+
def magnitude(n) when is_number(n), do: n
130
+
def magnitude([a, b]), do: 3 * magnitude(a) + 2 * magnitude(b)
131
+
end
132
+
```
133
+
134
+
```output
135
+
{:module, Day18, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:magnitude, 1}}
136
+
```
137
+
138
+
## Task 1
139
+
140
+
```elixir
141
+
flip = fn f -> &f.(&2, &1) end
142
+
143
+
input
144
+
|> Enum.reduce(flip.(&Day18.add/2))
145
+
|> IO.inspect(charlists: :as_list)
146
+
|> Day18.magnitude()
147
+
```
148
+
149
+
```output
150
+
[[[[7, 7], [7, 8]], [[8, 7], [0, 7]]], [[[6, 6], [6, 7]], 6]]
151
+
```
152
+
153
+
```output
154
+
3411
155
+
```
156
+
157
+
## Task 2
158
+
159
+
```elixir
160
+
for a <- input,
161
+
b <- input,
162
+
a != b,
163
+
m1 = Day18.magnitude(Day18.add(a, b)),
164
+
m2 = Day18.magnitude(Day18.add(b, a)),
165
+
reduce: 0 do
166
+
acc -> max(acc, max(m1, m2))
167
+
end
168
+
```
169
+
170
+
```output
171
+
4680
172
+
```
+100
2021/day18.txt
+100
2021/day18.txt
···
1
+
[[[6,[8,3]],[2,0]],[[[9,5],[9,1]],3]]
2
+
[[[9,[2,2]],[5,4]],[[[2,2],[9,6]],[7,7]]]
3
+
[[[0,[3,2]],1],[[0,[2,8]],[2,[0,4]]]]
4
+
[[4,4],[[[7,0],5],[3,1]]]
5
+
[[5,4],1]
6
+
[[[[7,6],4],9],[[9,1],9]]
7
+
[[[1,[7,8]],[[7,7],[1,6]]],[1,[6,[7,1]]]]
8
+
[[[[6,8],[5,6]],[[1,1],8]],[[[2,0],[3,1]],[2,[2,6]]]]
9
+
[[[6,3],[3,[7,1]]],8]
10
+
[[[9,4],[3,[0,6]]],[[2,[3,6]],[[9,8],[1,6]]]]
11
+
[9,[0,[[0,7],2]]]
12
+
[[[[8,4],7],[[9,2],[0,9]]],[[7,9],[8,[0,9]]]]
13
+
[[1,1],[[5,[3,8]],[3,[4,7]]]]
14
+
[[[9,[2,9]],[2,[2,9]]],[[[3,5],5],[[3,3],2]]]
15
+
[[[[5,4],9],0],[[[5,7],2],[[5,2],9]]]
16
+
[[2,[[1,0],[6,2]]],0]
17
+
[[[3,7],[7,6]],[[[2,8],5],[3,[9,7]]]]
18
+
[[2,[2,[8,8]]],[[[9,9],[1,1]],[[8,6],[0,3]]]]
19
+
[[8,1],[3,5]]
20
+
[[7,[[7,6],[2,0]]],4]
21
+
[[5,4],[[1,3],[5,[2,8]]]]
22
+
[7,9]
23
+
[[[[6,9],0],[1,[5,0]]],[[[6,4],3],7]]
24
+
[[[[3,7],3],[2,6]],[[0,4],[9,9]]]
25
+
[[[[1,5],[5,0]],[9,4]],[[[8,3],3],[8,[3,6]]]]
26
+
[[[[3,7],5],[[8,5],[1,5]]],[[0,6],[3,4]]]
27
+
[[[[4,0],2],[7,[8,4]]],[0,[5,[7,8]]]]
28
+
[[[[0,8],[0,4]],[9,3]],[[[5,4],[4,8]],[[1,6],[5,4]]]]
29
+
[[0,[0,3]],[[3,[1,5]],[[9,6],[0,6]]]]
30
+
[[9,[8,4]],[7,1]]
31
+
[[[[1,9],[7,7]],9],[[6,[4,5]],[8,[3,2]]]]
32
+
[5,[[2,[9,5]],[3,[4,0]]]]
33
+
[[[6,2],[[1,8],5]],6]
34
+
[[8,[6,[6,4]]],[0,[[9,8],7]]]
35
+
[[[[6,3],[8,0]],[8,[2,7]]],8]
36
+
[[[6,[3,6]],[[4,0],[4,7]]],[0,[[4,0],[4,5]]]]
37
+
[[[3,[8,1]],1],[2,3]]
38
+
[[[6,[7,0]],[[3,5],[3,4]]],7]
39
+
[[[[8,0],3],8],[[[1,6],3],[[0,5],2]]]
40
+
[[[3,7],[[9,8],8]],[[[8,4],7],[3,[1,7]]]]
41
+
[[[0,5],[[5,5],[7,8]]],[9,[5,[2,2]]]]
42
+
[[2,9],[[[7,4],4],[[8,0],[6,9]]]]
43
+
[[[[7,8],[8,8]],0],9]
44
+
[[[4,[0,6]],[[5,9],[0,1]]],[3,[6,7]]]
45
+
[[[7,[6,9]],[5,[6,4]]],[[[3,9],6],[[0,1],1]]]
46
+
[3,[[[6,9],7],[5,8]]]
47
+
[[[3,9],[[3,5],2]],[[[2,5],[4,6]],[8,0]]]
48
+
[[[9,7],3],[[[2,7],[0,9]],[3,[0,3]]]]
49
+
[[3,[4,0]],[[6,6],[4,5]]]
50
+
[[0,0],[[5,9],1]]
51
+
[[[6,8],[2,6]],[[[1,1],3],7]]
52
+
[[[4,4],[[1,0],[2,4]]],[2,6]]
53
+
[[[[6,0],6],[8,[9,9]]],[[4,2],[[1,8],[5,3]]]]
54
+
[[[[1,6],[4,3]],[5,5]],[[7,[9,9]],4]]
55
+
[[[[6,9],7],[9,3]],[[[9,6],5],0]]
56
+
[[3,[[7,2],[8,1]]],[[7,[3,0]],1]]
57
+
[0,[0,[1,3]]]
58
+
[[[0,5],[[6,1],[4,6]]],[[[0,4],8],[[4,5],9]]]
59
+
[[[[7,5],[7,0]],[6,[7,2]]],[7,[3,[4,1]]]]
60
+
[[3,3],[0,[6,2]]]
61
+
[[[3,8],[[7,3],6]],[[[0,8],3],[[8,9],[2,9]]]]
62
+
[[4,[[5,6],[4,0]]],[[7,[7,5]],[5,0]]]
63
+
[[[[2,5],[5,4]],9],[[[6,0],[0,0]],[[5,1],8]]]
64
+
[[2,[[1,7],7]],[[[4,5],[7,9]],0]]
65
+
[[[0,9],[[5,4],3]],3]
66
+
[[9,[[1,9],[1,6]]],[[9,[0,3]],[[8,8],[0,7]]]]
67
+
[[[[7,2],4],[7,8]],[[[4,1],[3,1]],[2,5]]]
68
+
[[[[1,8],3],[2,5]],[[0,[5,8]],[[1,3],[5,2]]]]
69
+
[[3,9],[[9,6],[5,[7,1]]]]
70
+
[1,[[3,[6,5]],[5,[2,7]]]]
71
+
[[[5,8],6],[8,[[9,4],[0,4]]]]
72
+
[0,[[5,[6,6]],[[7,4],[4,6]]]]
73
+
[[[[6,8],2],[[1,6],[8,2]]],6]
74
+
[7,2]
75
+
[[3,1],7]
76
+
[[[2,[9,5]],0],[[[7,3],4],8]]
77
+
[[[[0,0],[4,2]],5],[[8,6],2]]
78
+
[[1,[7,8]],[2,[[6,6],[5,7]]]]
79
+
[[[3,[6,0]],3],[[7,[4,4]],8]]
80
+
[[[9,[8,7]],[[4,2],4]],[[6,1],[[3,3],[2,2]]]]
81
+
[[[8,1],[[7,4],[5,9]]],9]
82
+
[[[2,[8,6]],[[9,8],2]],[[9,5],[1,[9,8]]]]
83
+
[[[[6,1],[3,1]],[[4,5],1]],[[[6,4],[6,2]],2]]
84
+
[[[[4,0],[0,1]],[[1,4],6]],7]
85
+
[[[[8,9],[0,2]],4],[[[9,8],8],[0,[0,6]]]]
86
+
[0,[[[0,9],1],7]]
87
+
[[1,[[3,7],3]],[[[2,4],3],0]]
88
+
[[[[7,6],3],8],[[5,5],9]]
89
+
[[2,[1,3]],[[[6,7],3],[[3,8],7]]]
90
+
[[[[0,6],6],6],[[5,[0,9]],[8,[2,4]]]]
91
+
[4,[[[3,0],[2,5]],[[7,4],1]]]
92
+
[[[[7,9],3],[0,[8,2]]],[[8,[3,4]],[[2,3],[1,6]]]]
93
+
[[[3,[6,3]],5],[[3,4],2]]
94
+
[[[[1,9],[0,3]],[0,8]],[[[4,2],[4,3]],[[8,9],5]]]
95
+
[[[[2,8],[4,9]],[[3,5],6]],[[6,[1,5]],[0,[9,7]]]]
96
+
[[6,3],[[[7,7],[1,7]],[[6,5],[0,8]]]]
97
+
[[1,[1,[5,8]]],7]
98
+
[[0,6],[9,[[3,4],0]]]
99
+
[[[[0,2],7],9],9]
100
+
[9,6]
+306
2021/day19.livemd
+306
2021/day19.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 19
4
+
5
+
## Section
6
+
7
+
```elixir
8
+
# File.read!("day19.txt")
9
+
input =
10
+
File.read!("day19.txt")
11
+
|> String.split("\n\n")
12
+
|> Enum.map(fn scanner ->
13
+
scanner
14
+
|> String.split("\n", trim: true)
15
+
|> Enum.drop(1)
16
+
|> Enum.map(fn coords ->
17
+
coords
18
+
|> String.split(",")
19
+
|> Enum.map(&String.to_integer/1)
20
+
|> Enum.zip(~w[x y z]a)
21
+
|> Map.new(fn {v, k} -> {k, v} end)
22
+
end)
23
+
|> MapSet.new()
24
+
end)
25
+
26
+
length(input)
27
+
```
28
+
29
+
```output
30
+
34
31
+
```
32
+
33
+
$$
34
+
\left\{
35
+
\begin{alignat*}{3}
36
+
b_{x_1} r_x + b_{x_0} = a_{x_1} \\
37
+
b_{x_2} r_x + b_{x_0} = a_{x_2}
38
+
\end{alignat*}
39
+
\right.
40
+
\left\{
41
+
\begin{alignat*}{3}
42
+
b_{y_1} r_y + b_{y_0} = a_{y_1} \\
43
+
b_{y_2} r_y + b_{y_0} = a_{y_2} \\
44
+
\end{alignat*}
45
+
\right.
46
+
\left\{
47
+
\begin{alignat*}{3}
48
+
b_{z_1} r_z + b_{z_0} = a_{z_1} \\
49
+
b_{z_2} r_z + b_{z_0} = a_{z_2} \\
50
+
\end{alignat*}
51
+
\right.
52
+
$$
53
+
54
+
Where $$r_x, r_y, r_z \in \{-1, 1\}$$ and $$a_{xyz}, b_{xyz} = \text{const}$$.
55
+
This mean that we need to solve:
56
+
57
+
$$
58
+
B_x x + b_0 = a_x \\
59
+
B_y y + b_0 = a_y \\
60
+
B_z z + b_0 = a_z
61
+
$$
62
+
63
+
Where:
64
+
65
+
$$
66
+
B_d = \begin{bmatrix}
67
+
{b_1}_d & 1 \\
68
+
{b_2}_d & 1 \\
69
+
\end{bmatrix}
70
+
d = \begin{bmatrix}
71
+
r_d \\
72
+
b_{d_0}
73
+
\end{bmatrix}
74
+
a_d = \begin{bmatrix}
75
+
{a_1}_d \\
76
+
{a_2}_d
77
+
\end{bmatrix}
78
+
$$
79
+
80
+
By applying [Cramer's Rule](https://en.wikipedia.org/wiki/Cramer%27s_rule) we can solve these
81
+
linear equations with:
82
+
83
+
$$
84
+
e_d = \frac{
85
+
\begin{vmatrix}
86
+
{b_1}_d & 1 \\
87
+
{b_2}_d & 1
88
+
\end{vmatrix}
89
+
}{
90
+
\begin{vmatrix}
91
+
{a_1}_d & 1 \\
92
+
{a_2}_d & 1
93
+
\end{vmatrix}
94
+
} = \frac{{b_1}_d - {b_2}_d}{{a_1}_d - {a_2}_d} \\
95
+
b_{d_0} = \frac{
96
+
\begin{vmatrix}
97
+
{a_1}_d & {b_1}_d \\
98
+
{a_2}_d & {b_2}_d
99
+
\end{vmatrix}
100
+
}{
101
+
\begin{vmatrix}
102
+
{a_1}_d & 1 \\
103
+
{a_2}_d & 1
104
+
\end{vmatrix}
105
+
} = \frac{{a_1}_d {b_2}_d - {b_1}_d {a_2}_d}{{a_1}_d - {a_2}_d}
106
+
107
+
```elixir
108
+
defmodule Day19 do
109
+
def rebase(base, pairs1) do
110
+
pairs0 = pairs(base)
111
+
# Take common points
112
+
pa = Map.take(pairs0, Map.keys(pairs1))
113
+
pb = Map.take(pairs1, Map.keys(pairs0))
114
+
115
+
# Merge them
116
+
[{{a, b, axes1}, {_, _, axes2}} = p0 | others] =
117
+
Map.merge(pa, pb, fn _, a, b -> {a, b} end)
118
+
|> Map.values()
119
+
120
+
p1 = Enum.find(others, fn {{x, y, _}, _} -> a in [x, y] end)
121
+
p2 = Enum.find(others, fn {{x, y, _}, _} -> b in [x, y] end)
122
+
123
+
axes = axes_transformations(axes1, axes2)
124
+
125
+
a_1 = a
126
+
a_2 = b
127
+
b_1 = reaxe(select_common(p0, p1), axes)
128
+
b_2 = reaxe(select_common(p0, p2), axes)
129
+
130
+
transform =
131
+
for i <- ~w[x y z]a, into: %{} do
132
+
a_1 = a_1[i]
133
+
a_2 = a_2[i]
134
+
b_1 = b_1[i]
135
+
b_2 = b_2[i]
136
+
det_b = b_1 - b_2
137
+
r = div(a_1 - a_2, det_b)
138
+
139
+
b_0 = div(b_1 * a_2 - a_1 * b_2, det_b)
140
+
141
+
{i, {r, b_0}}
142
+
end
143
+
144
+
new_points =
145
+
pairs1
146
+
|> Map.values()
147
+
|> Enum.flat_map(&[elem(&1, 0), elem(&1, 1)])
148
+
|> Enum.uniq()
149
+
|> Enum.map(&reaxe(&1, axes))
150
+
|> do_rebase(transform)
151
+
|> MapSet.new()
152
+
153
+
%{x: {_, sx}, y: {_, sy}, z: {_, sz}} = transform
154
+
scanner = %{x: sx, y: sy, z: sz}
155
+
156
+
{new_points, scanner}
157
+
end
158
+
159
+
defp do_rebase(points, transform) do
160
+
points
161
+
|> Enum.map(fn p ->
162
+
Map.merge(p, transform, fn _k, d, {r, b} -> d * r + b end)
163
+
end)
164
+
|> MapSet.new()
165
+
end
166
+
167
+
defp select_common(a, b) do
168
+
case {a, b} do
169
+
{{_, {_, x, _}}, {_, {_, x, _}}} -> x
170
+
{{_, {x, _, _}}, {_, {x, _, _}}} -> x
171
+
{{_, {_, x, _}}, {_, {x, _, _}}} -> x
172
+
{{_, {x, _, _}}, {_, {_, x, _}}} -> x
173
+
end
174
+
end
175
+
176
+
defp axes_transformations(a, b) do
177
+
Map.merge(a, b, fn
178
+
_, a, b -> {a, b}
179
+
end)
180
+
|> Map.values()
181
+
|> Map.new()
182
+
end
183
+
184
+
defp reaxe(point, axes) do
185
+
%{
186
+
x: point[axes[:x]],
187
+
y: point[axes[:y]],
188
+
z: point[axes[:z]]
189
+
}
190
+
end
191
+
192
+
def pairs(points) do
193
+
for a <- points,
194
+
b <- points,
195
+
a < b,
196
+
dx = abs(a.x - b.x),
197
+
dy = abs(a.y - b.y),
198
+
dz = abs(a.z - b.z),
199
+
into: %{},
200
+
do: {{dx ** 2 + dy ** 2 + dz ** 2, dx + dy + dz}, {a, b, %{dx => :x, dy => :y, dz => :z}}}
201
+
end
202
+
end
203
+
```
204
+
205
+
```output
206
+
{:module, Day19, <<70, 79, 82, 49, 0, 0, 26, ...>>, {:pairs, 1}}
207
+
```
208
+
209
+
```elixir
210
+
[first | rest] = Enum.map(input, &Day19.pairs/1)
211
+
212
+
{joinable, later} =
213
+
Enum.split_with(rest, fn pairs ->
214
+
s1 = MapSet.new(first, fn {k, _} -> k end)
215
+
s2 = MapSet.new(pairs, fn {k, _} -> k end)
216
+
217
+
case MapSet.size(MapSet.intersection(s1, s2)) do
218
+
66 -> true
219
+
x when x < 66 -> false
220
+
end
221
+
end)
222
+
223
+
{length(joinable), length(later)}
224
+
```
225
+
226
+
```output
227
+
{3, 30}
228
+
```
229
+
230
+
```elixir
231
+
# Distances between each pair of points in `first`
232
+
233
+
points_set = MapSet.new(hd(input))
234
+
235
+
{points_set, scanners} =
236
+
Enum.reduce_while(
237
+
1..34,
238
+
{points_set, joinable, later, []},
239
+
fn i, {set, joinable, later, scanners} ->
240
+
{time, {set, scanners}} =
241
+
:timer.tc(fn ->
242
+
Enum.reduce(joinable, {set, scanners}, fn new, {base, scanners} ->
243
+
{new, scanner} = Day19.rebase(base, new)
244
+
245
+
{MapSet.union(new, base), [scanner | scanners]}
246
+
end)
247
+
end)
248
+
249
+
IO.inspect(time / 1_000_000)
250
+
251
+
current = Day19.pairs(set)
252
+
253
+
Enum.split_with(later, fn pairs ->
254
+
s1 = MapSet.new(current, fn {k, _} -> k end)
255
+
s2 = MapSet.new(pairs, fn {k, _} -> k end)
256
+
257
+
MapSet.size(MapSet.intersection(s1, s2)) >= 66
258
+
end)
259
+
|> case do
260
+
{[], []} ->
261
+
{:halt, {set, scanners}}
262
+
263
+
{joinable, later} ->
264
+
IO.inspect({length(joinable), length(later)}, label: i)
265
+
{:cont, {set, joinable, later, scanners}}
266
+
end
267
+
end
268
+
)
269
+
270
+
MapSet.size(points_set)
271
+
```
272
+
273
+
```output
274
+
0.002822
275
+
1: {5, 25}
276
+
0.017052
277
+
2: {5, 20}
278
+
0.0355
279
+
3: {7, 13}
280
+
0.134655
281
+
4: {6, 7}
282
+
0.229952
283
+
5: {5, 2}
284
+
0.288351
285
+
6: {1, 1}
286
+
0.076665
287
+
7: {1, 0}
288
+
0.071942
289
+
```
290
+
291
+
```output
292
+
396
293
+
```
294
+
295
+
```elixir
296
+
for(
297
+
a <- scanners,
298
+
b <- scanners,
299
+
do: abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z)
300
+
)
301
+
|> Enum.max()
302
+
```
303
+
304
+
```output
305
+
11828
306
+
```
+949
2021/day19.txt
+949
2021/day19.txt
···
1
+
--- scanner 0 ---
2
+
-731,-763,-425
3
+
832,-512,-437
4
+
571,657,-514
5
+
594,551,-569
6
+
-604,638,718
7
+
-536,524,776
8
+
629,721,-564
9
+
-623,-444,440
10
+
-708,-610,437
11
+
550,-524,759
12
+
355,515,510
13
+
-683,877,-615
14
+
763,-622,-365
15
+
-833,-795,-362
16
+
-663,840,-668
17
+
-676,876,-848
18
+
7,-92,-35
19
+
560,-560,695
20
+
-559,539,599
21
+
528,-504,779
22
+
-709,-874,-390
23
+
457,445,563
24
+
841,-410,-363
25
+
-742,-511,374
26
+
422,463,367
27
+
28
+
--- scanner 1 ---
29
+
598,477,221
30
+
687,-702,-850
31
+
-586,-650,-945
32
+
-588,-636,-820
33
+
-676,-819,603
34
+
431,-621,738
35
+
-790,449,456
36
+
339,566,-635
37
+
386,708,-671
38
+
466,672,-647
39
+
245,-629,714
40
+
-674,520,398
41
+
-20,-191,-108
42
+
624,398,329
43
+
-712,486,-889
44
+
-851,477,396
45
+
-791,580,-833
46
+
627,330,296
47
+
623,-679,-824
48
+
-859,-833,629
49
+
697,-847,-874
50
+
-463,-586,-905
51
+
-607,554,-853
52
+
-789,-836,551
53
+
-168,-4,-10
54
+
413,-642,724
55
+
56
+
--- scanner 2 ---
57
+
676,816,-834
58
+
614,746,-853
59
+
-592,-743,-408
60
+
-72,47,-39
61
+
-744,-404,762
62
+
444,-703,786
63
+
753,-784,-474
64
+
-534,-783,-416
65
+
735,717,-765
66
+
568,482,582
67
+
-343,434,-675
68
+
-488,758,370
69
+
545,517,368
70
+
-489,888,446
71
+
-642,-821,-498
72
+
-351,372,-463
73
+
384,-705,874
74
+
-827,-527,719
75
+
624,-720,837
76
+
88,-28,74
77
+
503,604,524
78
+
-640,-593,761
79
+
-419,427,-552
80
+
690,-818,-490
81
+
-353,831,437
82
+
650,-734,-583
83
+
84
+
--- scanner 3 ---
85
+
-561,681,-898
86
+
-696,-781,-955
87
+
674,322,-753
88
+
-631,640,-859
89
+
421,399,364
90
+
-559,-639,519
91
+
451,-574,320
92
+
-599,-747,467
93
+
-813,515,442
94
+
809,328,-802
95
+
478,-579,460
96
+
-710,-656,-826
97
+
455,-597,-612
98
+
-600,-812,-818
99
+
555,-700,367
100
+
593,379,413
101
+
382,-629,-639
102
+
810,259,-767
103
+
-46,21,-86
104
+
-662,548,550
105
+
-618,-569,546
106
+
-710,453,457
107
+
-805,672,-885
108
+
479,482,472
109
+
444,-658,-572
110
+
75,-100,-5
111
+
112
+
--- scanner 4 ---
113
+
-720,-688,-429
114
+
75,21,146
115
+
-524,-443,905
116
+
-455,739,547
117
+
28,-141,13
118
+
-697,-360,919
119
+
826,-631,876
120
+
-556,623,540
121
+
710,450,-593
122
+
-545,-345,887
123
+
697,394,-509
124
+
767,-745,773
125
+
875,-803,856
126
+
614,-573,-535
127
+
542,624,862
128
+
-794,439,-772
129
+
561,-428,-543
130
+
-746,370,-754
131
+
-683,-626,-394
132
+
469,634,823
133
+
-628,431,-669
134
+
-754,-741,-370
135
+
741,613,-533
136
+
489,522,847
137
+
-374,623,575
138
+
664,-373,-571
139
+
140
+
--- scanner 5 ---
141
+
699,-825,730
142
+
537,-594,-346
143
+
346,566,583
144
+
-631,-481,703
145
+
-787,-523,790
146
+
859,752,-606
147
+
585,-767,662
148
+
424,-689,-351
149
+
-648,384,-472
150
+
684,-648,707
151
+
-709,511,419
152
+
-683,421,-534
153
+
-38,84,173
154
+
-707,350,-419
155
+
-342,-793,-586
156
+
765,684,-628
157
+
-573,-546,825
158
+
493,-563,-373
159
+
-785,510,549
160
+
701,831,-589
161
+
-718,375,476
162
+
-335,-697,-642
163
+
383,619,603
164
+
-293,-795,-521
165
+
347,799,590
166
+
117,6,18
167
+
168
+
--- scanner 6 ---
169
+
-716,-702,538
170
+
795,547,748
171
+
-711,527,-540
172
+
601,413,-940
173
+
-863,-529,-512
174
+
388,-501,-871
175
+
-723,-534,-539
176
+
787,759,810
177
+
-637,-524,557
178
+
719,670,755
179
+
300,-440,423
180
+
580,395,-842
181
+
-816,-655,-616
182
+
345,-571,505
183
+
554,-554,-934
184
+
-633,593,601
185
+
-741,560,752
186
+
547,-535,-827
187
+
753,381,-925
188
+
359,-597,479
189
+
-819,444,-482
190
+
10,13,-72
191
+
-664,-594,498
192
+
-770,424,-654
193
+
-726,498,649
194
+
195
+
--- scanner 7 ---
196
+
-582,-761,459
197
+
-453,-839,-862
198
+
804,-878,437
199
+
-612,749,581
200
+
436,398,564
201
+
-487,-795,-703
202
+
807,842,-463
203
+
750,-880,275
204
+
-549,511,-891
205
+
718,787,-531
206
+
145,-81,-100
207
+
-503,-738,369
208
+
-600,814,464
209
+
429,-893,-497
210
+
-599,645,571
211
+
-540,-758,410
212
+
718,-866,393
213
+
461,-908,-649
214
+
-523,537,-905
215
+
595,780,-455
216
+
-506,-902,-696
217
+
417,468,502
218
+
505,497,623
219
+
12,47,-20
220
+
-392,455,-950
221
+
443,-810,-670
222
+
223
+
--- scanner 8 ---
224
+
53,162,-22
225
+
967,695,948
226
+
770,-615,-548
227
+
-670,-668,425
228
+
968,599,931
229
+
956,564,873
230
+
-402,599,-642
231
+
-440,-235,-401
232
+
840,-611,-438
233
+
684,602,-426
234
+
609,-449,832
235
+
691,788,-464
236
+
-498,984,913
237
+
895,-586,-503
238
+
-501,913,878
239
+
167,129,170
240
+
695,623,-587
241
+
493,-550,825
242
+
-523,556,-616
243
+
-368,-412,-433
244
+
-478,-443,-393
245
+
-7,18,134
246
+
-390,903,852
247
+
-353,475,-643
248
+
609,-631,797
249
+
-691,-717,496
250
+
-674,-800,467
251
+
252
+
--- scanner 9 ---
253
+
523,-356,773
254
+
-764,463,-560
255
+
-425,-730,874
256
+
668,-366,749
257
+
728,-640,-825
258
+
67,173,60
259
+
903,419,-683
260
+
-787,551,-542
261
+
-403,-811,707
262
+
889,413,-586
263
+
749,-622,-839
264
+
-763,407,-508
265
+
741,-808,-815
266
+
-699,745,628
267
+
-523,-387,-566
268
+
-489,-747,745
269
+
-606,801,513
270
+
-724,-387,-543
271
+
-647,-369,-544
272
+
-682,846,572
273
+
658,516,448
274
+
518,532,446
275
+
460,523,469
276
+
94,-8,-68
277
+
885,388,-755
278
+
691,-430,723
279
+
280
+
--- scanner 10 ---
281
+
632,619,803
282
+
-337,-640,-546
283
+
746,-937,-943
284
+
-81,54,-168
285
+
821,-857,548
286
+
706,756,751
287
+
683,-855,672
288
+
-733,363,-817
289
+
-615,381,-906
290
+
-584,435,-808
291
+
-329,-782,-669
292
+
586,461,-730
293
+
659,730,711
294
+
-493,496,495
295
+
766,-822,-830
296
+
-338,-687,-635
297
+
-589,-913,412
298
+
721,-864,422
299
+
-601,-806,278
300
+
397,451,-676
301
+
-10,-104,0
302
+
-604,404,408
303
+
487,463,-794
304
+
775,-762,-933
305
+
-602,583,413
306
+
-461,-925,315
307
+
308
+
--- scanner 11 ---
309
+
-746,899,-576
310
+
407,869,433
311
+
-547,-309,328
312
+
-416,-384,339
313
+
-316,-483,-310
314
+
399,485,-678
315
+
698,-432,802
316
+
-46,-77,89
317
+
-648,857,-455
318
+
-726,877,401
319
+
-478,-429,-312
320
+
-744,850,-511
321
+
608,-772,-282
322
+
433,544,-625
323
+
629,-790,-380
324
+
-729,896,666
325
+
525,784,494
326
+
-451,-326,327
327
+
46,69,-60
328
+
359,887,502
329
+
470,509,-563
330
+
-434,-515,-324
331
+
456,-804,-297
332
+
-788,819,534
333
+
779,-460,686
334
+
597,-425,686
335
+
336
+
--- scanner 12 ---
337
+
363,-267,559
338
+
256,-401,547
339
+
-772,-682,-877
340
+
314,-661,-725
341
+
19,64,-38
342
+
-676,-711,473
343
+
-685,590,-796
344
+
-833,-770,417
345
+
-719,-516,-940
346
+
529,557,295
347
+
387,680,287
348
+
-625,644,776
349
+
244,-304,419
350
+
347,841,-808
351
+
407,944,-817
352
+
-702,-725,499
353
+
-173,172,-77
354
+
-738,-523,-833
355
+
-613,761,711
356
+
-722,549,-776
357
+
232,954,-788
358
+
-643,639,-799
359
+
312,-537,-863
360
+
305,-411,-763
361
+
482,646,296
362
+
-626,751,607
363
+
364
+
--- scanner 13 ---
365
+
292,-495,571
366
+
651,919,779
367
+
-175,-32,46
368
+
-939,696,356
369
+
-690,411,-464
370
+
-384,-810,562
371
+
-785,-685,-485
372
+
-795,451,-566
373
+
773,-408,-583
374
+
-906,399,-435
375
+
781,-531,-441
376
+
-455,-767,470
377
+
772,-497,-536
378
+
357,-612,559
379
+
-950,531,445
380
+
-455,-745,448
381
+
595,860,622
382
+
649,453,-298
383
+
-917,726,512
384
+
-20,152,68
385
+
-778,-675,-648
386
+
-763,-609,-482
387
+
509,416,-417
388
+
569,874,648
389
+
461,-602,572
390
+
521,550,-310
391
+
392
+
--- scanner 14 ---
393
+
-322,-641,670
394
+
-349,354,-648
395
+
-625,714,619
396
+
812,-715,-617
397
+
-491,-748,669
398
+
821,527,-792
399
+
909,550,885
400
+
-599,728,593
401
+
-294,286,-737
402
+
87,-111,72
403
+
354,-956,679
404
+
-668,-679,-347
405
+
425,-891,793
406
+
862,-818,-726
407
+
-387,-758,682
408
+
887,580,729
409
+
425,-913,771
410
+
-639,-800,-435
411
+
-356,278,-525
412
+
-46,-32,-48
413
+
899,577,-702
414
+
896,-755,-710
415
+
920,385,796
416
+
861,469,-784
417
+
-738,-741,-366
418
+
-681,773,462
419
+
420
+
--- scanner 15 ---
421
+
-863,636,832
422
+
887,603,374
423
+
-66,-152,-18
424
+
-406,-515,-665
425
+
-501,-905,785
426
+
542,-591,-441
427
+
790,520,-691
428
+
562,-667,653
429
+
888,610,607
430
+
-680,319,-645
431
+
-611,-836,857
432
+
813,415,-771
433
+
732,-702,658
434
+
668,-644,708
435
+
-784,760,860
436
+
-380,-439,-590
437
+
66,2,27
438
+
-839,277,-736
439
+
811,556,-859
440
+
-752,658,797
441
+
-576,-505,-555
442
+
-746,345,-682
443
+
543,-455,-365
444
+
851,590,554
445
+
-399,-914,859
446
+
436,-477,-381
447
+
448
+
--- scanner 16 ---
449
+
695,-489,-727
450
+
-393,764,-274
451
+
513,-404,724
452
+
733,406,705
453
+
788,-449,-811
454
+
804,-386,-777
455
+
-591,-456,576
456
+
-715,-313,-340
457
+
-544,907,364
458
+
135,43,-46
459
+
-534,924,338
460
+
-559,835,455
461
+
-315,762,-398
462
+
444,-463,823
463
+
424,417,-730
464
+
695,626,745
465
+
-693,-291,-340
466
+
-378,843,-372
467
+
425,-525,753
468
+
454,414,-693
469
+
-604,-446,472
470
+
-601,-248,-269
471
+
465,460,-686
472
+
-592,-563,407
473
+
749,580,604
474
+
76,148,91
475
+
476
+
--- scanner 17 ---
477
+
455,-760,-649
478
+
670,-470,334
479
+
569,454,608
480
+
-358,-652,-715
481
+
-522,413,-718
482
+
578,-408,376
483
+
-499,503,-639
484
+
-510,818,236
485
+
-465,-659,-734
486
+
530,478,-610
487
+
534,643,-733
488
+
-435,-673,316
489
+
-123,-22,19
490
+
-481,808,411
491
+
630,-482,500
492
+
-421,-818,-768
493
+
541,457,-771
494
+
-573,-797,318
495
+
-490,705,351
496
+
-535,-547,309
497
+
-502,454,-681
498
+
385,-756,-759
499
+
330,-731,-694
500
+
20,-66,-142
501
+
736,518,636
502
+
522,517,683
503
+
504
+
--- scanner 18 ---
505
+
488,-495,-482
506
+
753,833,793
507
+
575,545,-722
508
+
437,-478,-662
509
+
-380,740,-476
510
+
-589,-884,-619
511
+
-447,-668,405
512
+
512,-794,706
513
+
66,67,-124
514
+
-535,581,492
515
+
-383,-610,455
516
+
555,-671,789
517
+
-392,808,-633
518
+
-659,-782,-672
519
+
-477,812,-495
520
+
741,783,712
521
+
-641,-817,-476
522
+
721,728,746
523
+
-433,523,401
524
+
513,-605,602
525
+
613,677,-617
526
+
188,-120,-51
527
+
-553,-645,460
528
+
400,-493,-422
529
+
-598,533,370
530
+
546,787,-712
531
+
532
+
--- scanner 19 ---
533
+
680,468,656
534
+
-895,-366,652
535
+
-732,-787,-709
536
+
-801,-610,-698
537
+
451,-753,587
538
+
600,-429,-518
539
+
-808,-712,-655
540
+
-85,174,-91
541
+
381,-734,525
542
+
480,-665,466
543
+
-787,899,-508
544
+
-696,913,386
545
+
-631,962,384
546
+
-752,920,482
547
+
499,-445,-344
548
+
-864,885,-423
549
+
-821,796,-468
550
+
523,758,-784
551
+
56,66,25
552
+
466,693,-633
553
+
593,624,698
554
+
715,682,633
555
+
501,782,-567
556
+
-897,-420,814
557
+
459,-483,-564
558
+
-883,-452,696
559
+
560
+
--- scanner 20 ---
561
+
397,-456,465
562
+
822,541,-705
563
+
-805,-570,-623
564
+
484,-683,-391
565
+
-592,793,-393
566
+
-867,737,670
567
+
-592,-860,531
568
+
-506,805,-437
569
+
-881,820,497
570
+
-560,807,-275
571
+
432,554,511
572
+
-12,12,62
573
+
780,662,-607
574
+
467,492,474
575
+
406,-399,601
576
+
773,606,-703
577
+
328,-770,-433
578
+
-893,-541,-502
579
+
-503,-915,463
580
+
330,-529,600
581
+
408,439,440
582
+
-715,-853,455
583
+
-849,835,649
584
+
542,-805,-456
585
+
-129,-146,27
586
+
-874,-471,-564
587
+
588
+
--- scanner 21 ---
589
+
533,528,-756
590
+
635,945,504
591
+
924,-707,-431
592
+
926,-248,469
593
+
-453,651,678
594
+
743,907,422
595
+
18,113,48
596
+
-426,-601,-285
597
+
-587,-409,730
598
+
-602,-306,668
599
+
934,-310,681
600
+
450,651,-713
601
+
-736,841,-422
602
+
788,-764,-440
603
+
858,-303,558
604
+
637,717,-755
605
+
-701,958,-484
606
+
685,867,414
607
+
-219,-659,-318
608
+
789,-634,-364
609
+
-609,608,678
610
+
-494,-457,635
611
+
-602,695,664
612
+
-672,954,-527
613
+
-322,-639,-423
614
+
615
+
--- scanner 22 ---
616
+
665,-972,357
617
+
157,-75,5
618
+
-645,524,554
619
+
-661,-821,715
620
+
552,-766,-295
621
+
572,402,640
622
+
534,-897,368
623
+
-544,439,-366
624
+
-641,414,484
625
+
569,492,-403
626
+
596,-852,-283
627
+
-616,479,429
628
+
-479,-856,715
629
+
6,-31,124
630
+
618,534,-400
631
+
434,-798,-281
632
+
593,563,629
633
+
-537,458,-259
634
+
-703,405,-322
635
+
-338,-477,-268
636
+
-580,-849,831
637
+
758,440,633
638
+
569,-955,356
639
+
528,455,-423
640
+
-490,-509,-253
641
+
-511,-491,-351
642
+
643
+
--- scanner 23 ---
644
+
388,-809,-352
645
+
-367,872,532
646
+
-415,-631,622
647
+
743,-603,724
648
+
-753,552,-643
649
+
562,-642,690
650
+
139,81,144
651
+
451,-707,-384
652
+
-381,-642,874
653
+
383,456,849
654
+
-411,-684,-537
655
+
416,-685,-273
656
+
-384,-613,831
657
+
-338,776,398
658
+
412,553,858
659
+
399,591,733
660
+
-264,869,422
661
+
-733,574,-623
662
+
-414,-599,-703
663
+
674,-497,728
664
+
48,-39,41
665
+
389,865,-737
666
+
-669,584,-587
667
+
463,856,-635
668
+
-348,-718,-636
669
+
391,787,-525
670
+
671
+
--- scanner 24 ---
672
+
-784,-392,606
673
+
-484,366,661
674
+
736,683,764
675
+
-663,-858,-769
676
+
833,-740,823
677
+
-553,-789,-841
678
+
821,-458,-849
679
+
-765,-867,-843
680
+
700,495,-558
681
+
87,-2,28
682
+
-325,324,752
683
+
790,830,797
684
+
705,-593,-833
685
+
836,-846,942
686
+
-418,392,698
687
+
830,-555,-820
688
+
1,-137,118
689
+
870,-733,933
690
+
662,640,-670
691
+
-380,807,-844
692
+
-301,683,-816
693
+
-588,-458,571
694
+
696,601,-489
695
+
-412,705,-781
696
+
-758,-468,681
697
+
661,785,811
698
+
699
+
--- scanner 25 ---
700
+
500,-759,-543
701
+
637,-476,865
702
+
844,524,-809
703
+
691,-401,789
704
+
755,549,-692
705
+
-670,-822,952
706
+
680,-578,858
707
+
374,779,921
708
+
-536,581,-571
709
+
-543,-454,-324
710
+
326,-743,-442
711
+
-738,485,812
712
+
-605,-435,-394
713
+
-832,-768,954
714
+
827,534,-783
715
+
396,700,869
716
+
-697,522,832
717
+
-24,26,176
718
+
-643,582,-740
719
+
-484,-523,-423
720
+
546,-705,-402
721
+
-526,594,-675
722
+
36,-123,83
723
+
-648,564,835
724
+
-714,-736,940
725
+
311,819,948
726
+
727
+
--- scanner 26 ---
728
+
-609,-865,-696
729
+
-730,-552,628
730
+
320,796,-676
731
+
-480,446,-760
732
+
-789,-814,-679
733
+
752,-686,698
734
+
86,-103,-33
735
+
-54,-53,105
736
+
601,-621,755
737
+
-543,462,-794
738
+
-688,-396,541
739
+
312,517,722
740
+
462,-422,-642
741
+
426,-451,-511
742
+
-557,806,840
743
+
535,-710,720
744
+
-619,825,770
745
+
366,785,-669
746
+
-849,-902,-681
747
+
532,555,762
748
+
-498,737,741
749
+
444,-531,-542
750
+
-665,-610,506
751
+
323,826,-713
752
+
-583,555,-710
753
+
486,501,621
754
+
755
+
--- scanner 27 ---
756
+
440,-949,710
757
+
-548,356,729
758
+
-860,601,-538
759
+
464,-767,-452
760
+
653,723,873
761
+
-846,-908,-728
762
+
440,436,-892
763
+
-730,-861,516
764
+
4,-62,-113
765
+
541,420,-718
766
+
407,-702,-603
767
+
581,741,842
768
+
484,727,848
769
+
442,-791,-669
770
+
-674,-844,415
771
+
458,-926,798
772
+
-923,-894,-813
773
+
-880,-805,-768
774
+
-93,-141,27
775
+
-550,496,745
776
+
400,474,-672
777
+
-571,298,738
778
+
-615,-768,460
779
+
-867,703,-581
780
+
-791,778,-527
781
+
406,-925,854
782
+
783
+
--- scanner 28 ---
784
+
647,354,627
785
+
754,-710,818
786
+
-32,-37,79
787
+
-607,574,728
788
+
706,-823,-325
789
+
-440,806,-361
790
+
811,-701,682
791
+
-630,680,673
792
+
686,-718,-428
793
+
-604,-428,344
794
+
627,391,574
795
+
-907,-614,-778
796
+
593,431,-839
797
+
681,-777,683
798
+
-481,-385,427
799
+
452,429,-751
800
+
557,452,-671
801
+
9,100,-69
802
+
-911,-657,-807
803
+
-554,700,-421
804
+
648,-856,-532
805
+
-665,510,678
806
+
640,355,394
807
+
-670,-386,531
808
+
-794,-719,-842
809
+
-418,699,-345
810
+
811
+
--- scanner 29 ---
812
+
345,-686,278
813
+
590,445,375
814
+
-10,-33,-90
815
+
730,443,391
816
+
-830,567,-808
817
+
-329,-599,712
818
+
-452,-400,-567
819
+
725,770,-497
820
+
-454,-606,663
821
+
788,466,382
822
+
580,746,-507
823
+
359,-589,272
824
+
557,720,-571
825
+
-688,531,-855
826
+
-520,-433,-570
827
+
-571,763,607
828
+
363,-758,247
829
+
-794,543,-728
830
+
-464,-557,820
831
+
-121,76,13
832
+
-599,-325,-596
833
+
-469,671,559
834
+
-529,590,644
835
+
520,-828,-781
836
+
507,-818,-949
837
+
499,-842,-763
838
+
839
+
--- scanner 30 ---
840
+
898,-783,-440
841
+
922,437,482
842
+
-471,-599,844
843
+
754,-763,593
844
+
74,-14,20
845
+
-699,-844,-819
846
+
905,-782,548
847
+
7,-163,-135
848
+
864,402,436
849
+
-386,-589,679
850
+
427,680,-886
851
+
405,573,-902
852
+
-465,303,-496
853
+
-661,-982,-715
854
+
-477,-574,623
855
+
-728,245,476
856
+
-719,-949,-922
857
+
541,574,-826
858
+
-570,326,-576
859
+
781,-845,-405
860
+
-555,248,370
861
+
-606,305,-408
862
+
907,-709,651
863
+
894,-740,-469
864
+
916,504,488
865
+
-697,342,327
866
+
867
+
--- scanner 31 ---
868
+
246,-795,-450
869
+
689,777,-513
870
+
-737,-654,-829
871
+
659,821,460
872
+
300,-430,432
873
+
-748,371,-546
874
+
-636,391,-522
875
+
-451,-517,506
876
+
555,774,586
877
+
-738,444,-507
878
+
-33,-82,-118
879
+
-476,718,803
880
+
329,-622,-464
881
+
-576,-488,551
882
+
231,-643,-482
883
+
-498,868,705
884
+
632,681,465
885
+
-737,-472,-794
886
+
-853,-553,-822
887
+
631,669,-596
888
+
5,80,24
889
+
344,-589,466
890
+
-506,-492,441
891
+
517,728,-493
892
+
-469,691,760
893
+
237,-596,485
894
+
895
+
--- scanner 32 ---
896
+
299,519,833
897
+
-547,650,-617
898
+
395,-426,414
899
+
-954,-698,761
900
+
643,-437,-429
901
+
-715,929,492
902
+
-555,612,-825
903
+
-856,-676,911
904
+
-911,-705,734
905
+
313,846,-260
906
+
-657,-723,-474
907
+
-658,986,590
908
+
267,489,859
909
+
-714,907,743
910
+
371,-538,434
911
+
342,863,-343
912
+
671,-321,-510
913
+
-592,-668,-449
914
+
-702,-598,-445
915
+
-134,142,-43
916
+
-587,540,-648
917
+
239,648,792
918
+
356,-436,487
919
+
678,-437,-611
920
+
-22,23,114
921
+
271,842,-392
922
+
923
+
--- scanner 33 ---
924
+
353,649,717
925
+
632,-572,-385
926
+
627,-425,511
927
+
569,-375,575
928
+
-478,613,-778
929
+
566,-759,-427
930
+
420,506,769
931
+
759,692,-309
932
+
455,702,787
933
+
742,512,-360
934
+
592,-430,681
935
+
-443,636,-564
936
+
-678,-709,356
937
+
744,452,-272
938
+
-665,-529,392
939
+
-606,857,594
940
+
-792,-285,-709
941
+
-685,-476,355
942
+
39,-2,98
943
+
-561,738,693
944
+
-31,148,10
945
+
-849,-421,-700
946
+
-565,571,-622
947
+
-538,915,708
948
+
443,-676,-384
949
+
-719,-420,-776
+80
2021/day2.livemd
+80
2021/day2.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 2
7
+
8
+
## Load input
9
+
10
+
We do parsing there, as it will help us with the latter tasks. Pattern matching
11
+
is the simplest approach there, as input is in form of:
12
+
13
+
```
14
+
forward 10
15
+
up 20
16
+
down 30
17
+
```
18
+
19
+
We need to `trim/1` input to make sure that the last newline will not interrupt
20
+
`String.to_integer/1` calls.
21
+
22
+
```elixir
23
+
stream =
24
+
File.stream!("day2.txt")
25
+
|> Stream.map(fn input ->
26
+
case String.trim(input) do
27
+
"forward " <> n -> {:forward, String.to_integer(n)}
28
+
"up " <> n -> {:up, String.to_integer(n)}
29
+
"down " <> n -> {:down, String.to_integer(n)}
30
+
end
31
+
end)
32
+
```
33
+
34
+
```output
35
+
#Stream<[
36
+
enum: %File.Stream{
37
+
line_or_bytes: :line,
38
+
modes: [:raw, :read_ahead, :binary],
39
+
path: "day2.txt",
40
+
raw: true
41
+
},
42
+
funs: [#Function<47.58486609/1 in Stream.map/2>]
43
+
]>
44
+
```
45
+
46
+
## Task 1
47
+
48
+
```elixir
49
+
{h, d} =
50
+
stream
51
+
|> Enum.reduce({0, 0}, fn
52
+
{:forward, n}, {h, d} -> {h + n, d}
53
+
{:up, n}, {h, d} -> {h, d - n}
54
+
{:down, n}, {h, d} -> {h, d + n}
55
+
end)
56
+
57
+
h * d
58
+
```
59
+
60
+
```output
61
+
1499229
62
+
```
63
+
64
+
## Task 2
65
+
66
+
```elixir
67
+
{h, d, _} =
68
+
stream
69
+
|> Enum.reduce({0, 0, 0}, fn
70
+
{:forward, n}, {h, d, a} -> {h + n, d + a * n, a}
71
+
{:up, n}, {h, d, a} -> {h, d, a - n}
72
+
{:down, n}, {h, d, a} -> {h, d, a + n}
73
+
end)
74
+
75
+
h * d
76
+
```
77
+
78
+
```output
79
+
1340836560
80
+
```
+259
2021/day20.livemd
+259
2021/day20.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 20
4
+
5
+
## Section
6
+
7
+
```elixir
8
+
[algo, board] =
9
+
File.read!("day20.txt")
10
+
|> String.split("\n\n")
11
+
12
+
board =
13
+
board
14
+
|> String.split("\n", trim: true)
15
+
|> Enum.with_index()
16
+
|> Enum.flat_map(fn {row, y} ->
17
+
:binary.bin_to_list(row)
18
+
|> Enum.with_index()
19
+
|> Enum.map(fn {c, x} -> {{x, y}, if(c == ?#, do: 1, else: 0)} end)
20
+
end)
21
+
|> Map.new()
22
+
23
+
defmodule Day20 do
24
+
defmodule Image do
25
+
defstruct [:board, :background]
26
+
27
+
@behaviour Access
28
+
29
+
def new(board, background \\ 0),
30
+
do: %__MODULE__{board: board, background: background}
31
+
32
+
def dims(%__MODULE__{board: board}) do
33
+
{{min_x, min_y}, {max_x, max_y}} = board |> Map.keys() |> Enum.min_max()
34
+
35
+
{min_x..max_x, min_y..max_y}
36
+
end
37
+
38
+
def lighted(%__MODULE__{background: 1}), do: :inf
39
+
def lighted(%__MODULE__{board: board}), do: board |> Map.values() |> Enum.sum()
40
+
41
+
@impl Access
42
+
def fetch(%__MODULE__{} = img, {_, _} = key) do
43
+
case Map.fetch(img.board, key) do
44
+
{:ok, value} -> {:ok, value}
45
+
:error -> {:ok, img.background}
46
+
end
47
+
end
48
+
49
+
def fetch(_data, _key), do: :error
50
+
51
+
@impl Access
52
+
def get_and_update(_data, _key, _func), do: :error
53
+
54
+
@impl Access
55
+
def pop(_data, _key), do: :error
56
+
57
+
defimpl Inspect do
58
+
import Inspect.Algebra
59
+
60
+
def inspect(%@for{} = img, _opts) do
61
+
{min_x..max_x, min_y..max_y} = @for.dims(img)
62
+
63
+
display =
64
+
for y <- (min_y - 1)..(max_y + 1) do
65
+
row =
66
+
for x <- (min_x - 1)..(max_x + 1) do
67
+
if img[{x, y}] == 1, do: "█", else: " "
68
+
end
69
+
70
+
concat([concat(row), line()])
71
+
end
72
+
73
+
concat([
74
+
"#Image<{#{max_x - min_x + 1}x#{max_y - min_y + 1}}",
75
+
line(),
76
+
concat(display),
77
+
">"
78
+
])
79
+
end
80
+
end
81
+
end
82
+
83
+
defmodule Algo do
84
+
defstruct [:desc]
85
+
86
+
@behaviour Access
87
+
88
+
def new(desc), do: %__MODULE__{desc: desc}
89
+
90
+
@impl Access
91
+
def fetch(%__MODULE__{desc: desc}, pos) do
92
+
loc = rem(pos, 512)
93
+
{:ok, if(binary_part(desc, loc, 1) == "#", do: 1, else: 0)}
94
+
end
95
+
96
+
@impl Access
97
+
def get_and_update(_data, _key, _func), do: :error
98
+
99
+
@impl Access
100
+
def pop(_data, _key), do: :error
101
+
end
102
+
103
+
def get_bits(img, {x, y}) do
104
+
digits =
105
+
for dy <- -1..1,
106
+
dx <- -1..1,
107
+
do: img[{x + dx, y + dy}]
108
+
109
+
Integer.undigits(digits, 2)
110
+
end
111
+
112
+
def enchance(img, algo) do
113
+
{min_x..max_x, min_y..max_y} = Image.dims(img)
114
+
115
+
board =
116
+
for y <- (min_y - 1)..(max_y + 1),
117
+
x <- (min_x - 1)..(max_x + 1),
118
+
into: %{},
119
+
do: {{x, y}, algo[get_bits(img, {x, y})]}
120
+
121
+
Image.new(board, algo[512 - img.background])
122
+
end
123
+
end
124
+
125
+
alg = Day20.Algo.new(algo)
126
+
img = Day20.Image.new(board)
127
+
```
128
+
129
+
```output
130
+
#Image<{100x100}
131
+
132
+
█ █ █ ██ ████████ ██ █ █ ███ █ ██ ██ █ ███ █ ██ █ █ █ ██ ███ █ ██ ██ █ ██ █
133
+
███ █ █ █ █ ██ ██ █ ████ ██ █ █ ███ █ █ █ █ ███ █ █ ███ ██ ██████ █ █ █████
134
+
██ █ ███ █ █ ███ ██ ███ █ █ █ █ █ █ ██ ███ ███ ██████ ████ █ █ ██ █ ██ ████ █ ██
135
+
█ ██ ████████ ██ █ █ █ █ ██ █ █ █ █ ██ ██ █ █ █ ██ █ █ █ ██████ █ █ █
136
+
███ █ ██ ████ █ █ █ ███ ███ ██ █ █ ███ █ ██ █ ██ ███ █ ██ ██ ██ █ █ ████ █ █
137
+
████ ███ █ ███ █ █ █ █ █████████ ████ █ █ ██ ██ █ █ █ █ █ █ █ █ ███ ██ ██
138
+
███ █ █████ ████ ██ ████ █ █████ ██ ██ ████ ███ ███ ██ █ █ █ ██████ ██ █ ██ █
139
+
█ █ █ ███ █ █ █ █ ████ ████ █ █ █ █ █ █ █ ██ █ █ █ █ █████ ██ █ █ ███
140
+
██ ██ ███ █ █ █ █ █ ████ █ ██ ███ █ █ █ ██ █ █ ██ ███ ███ █ █████ █ █
141
+
██ █ █ █ █ ██ █ ██ ███ ███ ██ █ █ █████ █ ██ █ ███ █ █ ██ ███ █ █ ████ ██ ██████
142
+
█ █ ████ ███ █████ ███ ██ ██ ████ ██ ██ █████████ █ █ ████ ██ █ █ ██ █ ██
143
+
█ █ █ █ █ █ █ █ █ ███ ██ █ ██ █ █ ██ █ █████ █ ███ ██ █ █ █ ██ ██ ██████ ██
144
+
██ ████ ██ █ ███████ ██ ██ ██ ████ ████ ██ ████ █ ███ █ ███ ██ █ ████ ███ ██
145
+
█ █ █ █ █ █ █ █ █ █████ █ █ ███ █ ██ █████ ██ █ █ █ ██ █ █ █ ███ █ █ █ █ █
146
+
██ █ █ █ ███ ███ ██ ████ ███ █ ██ █ █ ██ ███ ██ █ █ ██ █ ██ █ ██ ██ █ █ █ █ █ ███
147
+
█ ██ █ █ █ █ ███ ██ ███████ ███ █ █ █████ ███ █ █ ███ ███ ███ ██████ █ █ █ █████ █
148
+
████ █ ████ █ ████ ██ ████ ██ █ ██████ ███ ███ █ █ █ █ ██ ███████ ██ █ ████ ██ █
149
+
██ █ ███ ██ ██ ███ █ █ █ █ ██ ███ ██ ██ █ ████ █ █ █ ████ █ ██ █ █ █ ██ █
150
+
█ █ █ ██ ███ █ ████ ██ ██ █ █ ██ ██ ██ ███ ██ ██ █ ███ ███ █ █ ███ █
151
+
███ █ █ ██ ████ █ ██ ███ █ ██ █ █ █ █ ███ ██ ███ █ █ █ █ █ █████ █ ████ ██ ████ ██
152
+
█ █ █ ██ █ █ █ ███ ██████████ ██ █ ████ ██ ██ ███ ██ █ ██ █ █ █ ██ ███ █
153
+
█ █ ██ █ █ █ █ ██████████ ███ █ █ █ ██ █████ █ ██ █ ████ ███ █ █ ███ ███ ██ █
154
+
███ █ ██ ██ ████ █ ████ ██ ██████ █ █ █ ██ █████ ████ ██ ████ ██████ █ ██ ██ █
155
+
██ █████ █ ██ ███ ███ █ █ █ ██████ █ ████ ████ ██ ██ ██ ██ █ █ ████ █████ ██████
156
+
██ █ █ ███ █ ████ █ ████ ██ █ ████ ██ ████ ██ █ ███ █ ███ █ █ █ ██ █
157
+
█ ███ ██ ██ █ ██ ██ █ █ ███ ██ █ █ █ ██ █ █ ██ █ █ █ ██ ██ █ █ █ █ █ ██ █
158
+
█████ █ ███ ███ █ █ ██ ███ ███ ██ ██ █ ███ █ ██ ███ █ ███ ██ ██ █ ██ ███ ████ ███
159
+
█ ████ █ █ ███ ██ █ ██ ██ █ █ █ ██ █ █ █ █ ██ █ ██ ██████ ██ ████ ██ █ █
160
+
█ █ █ ██ ██ ██ ███ █ ███ █ ██ █ █████ █ █ ██ ███████ ██ █ █ ██ ████ █████ █ █ ██
161
+
█ █ █ █ ██ ██ ██ ██ █ ██ ██ ███ █ █ █ ██ █ █ █ ██ ███ █ ███ █ █ ██
162
+
█ █ ████ █ ██ █ ███ ██ █ ██ █████████ ███ ██ ██ █ █ █ █ ██ ███ ██ █
163
+
███ ██ █ █ █ ██ ██ ██ ██ █ █ █ ██ █ ██ █ ██ █ ██ ██ █ █ ████ ███ █ ██ ██ █ ███ ██
164
+
███ █ ██████ █ ███ ██ ███ ██ █ ██████ ███ ███ █ ██ ██ █ ██ ██ ██ █ █ ██ ██ █
165
+
██ █ █ ██ ██ █ █ ████ ██ █ █ █ ██ █████ ██ ██ █ ███ ███ ███ █
166
+
██ ███ █ █ █ █ ██ █ ██ ████ ███ ██ █████ ██ █ ██ ██ █ █ █ ██████ █ █ ███
167
+
██ ██ █ ███ █ ███ █ █ ███ ████ ██ █ █ █ ████ █ ████ ██ ███ █ ██ ██ ████ ███ █ █ ██ ██
168
+
█ █ █████ ██ █ ██ ███ █ █ █ █ █████████ ██ ██ █ █ ███ █ ██ ████████ █ ██
169
+
██ ██ ██ ██ ██ ███ █ █ ████ █ █ █ ███ █ █ █ █ ███ █ █ ██ ██ ██ █ █
170
+
█ ██ █████ ██ █ ███ ██ ██ ██ █ █ █ █ █ █ █████ █ ██ █ ██ █ █ ████ ██
171
+
██ ████ ██ █ ███ ████ ███ █ ██ ██ █ ██ █ ███ ███ █ █ ██████ █ █████ ██ █ ███ █ █
172
+
█ █ █ █ ███ █ █ ██ ███ █ ██ ████ █ █ █████ █ ███ ██████ █ ███ ██ ████ █ ██ █ █
173
+
█ ██ ██ █ ██ █ ██ █ █ █ █ ██ ██ █ ██ █ ██ █ █ ██ ███ ███ ██ █ █ █ ██
174
+
███ ██ ██ █ █ ██ ████ ███ █ ████ ███ █ ██ █ █ █ ███ █ █ ███ █ ████ ██ █ █ ████
175
+
█ █ ██ ██ █ ██ █ █ ██ ██ ███ ███ ████ ██ ███ █ ██ ██ ██ ████ █ █ ██ ██ █
176
+
█ █ ██ █ █ ██ █ ████ ███████ ██ █ █ ██ █ █ ███ ███ █ ██ █ ██ █ ██ ██ █ █ ███ █
177
+
████ █████ ██ ██ █████ █ █ ██ ██ ███ █ ███ █ █ ██ ███ ███ █████ ██ █
178
+
█ ███ ███ █ █ █ ██████ ███ ████ █████ ███ ███ ███ ██ █ ██ █ ██ ██ █ ███ █████
179
+
█ █ ██ █ ████ █████ ███ █ █████ █ █ █ █ █ ██ ██ █ █ █ █ ███ ███ ███ █████ █ ██ █ █ █ █
180
+
█ █ █ █ ██ █ ████ ███ █ █ ████████ ████ █ ██ █████ █ █ █ ███ █ █ ████ █ █
181
+
██ ███ ███ █ ██ █ █ █ ████ █ ███ ██ █ █ ██████ ██ ██ █ █ ████ █ ███ █
182
+
██ ████ ██ █ █ ████ █ ██ ██ ██ ███ █ ██ █ █ ██ █████ █████ █ █ █ █ ██
183
+
█ ██ █ ███ █ █ ██ ███ ███ ██ █ ██ ███ ████ █ █ █ █ ██ █ █ █ █████ █ █ █ █
184
+
█ ██ ███ ███ ███ █ █ █ ██ █ ███ ███ █ ██ █ █ ███ ██ █ ██ █ ██ ██ ██ █
185
+
███ █ █ █ ███ ███ █ █ █████ ████ █ █ ██ █████ █ ███ █ █ ███████ ████ █ ██
186
+
█ ██ █████ █ ██ ███ ██ █ █ ██ ██ ██ █ █ █ █ ███ █ ██ █ ██ ██ █ █ ██ ██ ███ █ █ ██
187
+
██ █ ████ ██ █ █████ █ █ ██████ ███ █ █ ██ ██ ██ █ ██ █ █ ██ ██ █ █ █ █ █ █ █ ██ █
188
+
█ ███████ █ █ ██ █ █ █ █ ████ █ █ █ █ █ ████ █ █ █ █ ██ ██ ██ ██ █ █
189
+
██ █ ████ █ █ █ ████████ █ █ ███ █ ████ █ █████ ██ ████ █ ███ ██ █ █ █ ██ █████
190
+
██ █ ██ █ █ █ █ █ █ █████████ █████ █ ███ █ ██ ██ █ ██ ███ ██ █ █ █ █ ████ █ █ ████ █
191
+
█████ ████ ██ ██ █ █ █ ██████ █ █ █ █ █ █ █ ██ █ █ ███ █ █ ████ ███ ██ █ █ █ █
192
+
██ █ ███ ██████ █ █ █ ██████ ██ █ █ ██████ ███ ██ █████ ████ █ █ █ ██ ███ █ ██ ██
193
+
█ ████ ██ █ █ █ █ ███ ██ █ ██ █ █ █████ ██ ██ █ ████ ███ █ █ ██ ██ ████ ███
194
+
██ ███ █ ███ █ ██ █ ██ ██ ███████ ██ █ █ ████ █ ████ ████ ███ ██ ██ ██ █ █ █ █ █
195
+
██ █ ██████ █ █ ██ ██████ █████ ███ █ ███ ██ █ ███ █ █ █ ███ █ ████ ████ ██ ██
196
+
████ █ ██ ██ █ █ █ ██ █ █ ██ █ ██ █ ███████ █ ██ ███ █ █ ███ ████ ███ █ █ █
197
+
█ ██ █ █ ██ ████ ███████ ██ █ ██ █ █ ██ █ ███ █ █ █ ███ █ █ ████ █ ██ █ █
198
+
██ █ ██ ██ █ █ █ ███████ ██ █ ███ █ ███ █ ██ █ █ █ █ █ ██ ██ █ ███ ███ ██ ██
199
+
█ █ ███ █ ██ █████ █ ██ █ ██ ███ █ █ █ ██ █████ █████ ███ █ ████ █ █ ███ █
200
+
█ ████ █ █ █ █ ██████ ██ ██ ██ █ █ █ █ █ ██ █ ████████████ ███ ████ ███ ███
201
+
█ █ █ █ ██ ██ █ █ █ ████ ██ ██ █ █ █ ██ ██ █ █ █ █ █ █ ███ █ █████ ██ ███ █ █
202
+
█ █ ██ ███ █ █ ███ █ █ █ ██ ██ ████████ █ █ █████ █ █ █ ██ █ ██ ████
203
+
█ █████ █ ██ ███ █ █ █ █ ███ ██ █ ██ ██ █ █████ █ █ ██ █ ███ ██ █ █ ██ █ █ █ █
204
+
███ █ █ █ █ ██ █ █ █ █ █ █ █ ███ ██ ████ ██████ █ █████ ███ ██ █ █
205
+
█ █ █ ██ █ █ ████ █ █ █████ █ █ █ █ ██ ██ █ █ █ █████ █ ██ █
206
+
█ ████ █ █ █ ██ ██ █ █ █ ██ ██ ██ ██ ██ █ █ █ ██ ██ ██ █ ██ █ █ ██ █ █
207
+
█ ████ ███ █████ █ █ ████ ██ █████ ██ ███ █ ███ ██ ██ ██ █ █ █ ███ █
208
+
█ █ ████ █ ██ █ █ ██████ ███████ █ ██ ███ ███ █ █ ██ █ ████ ███ █ ███ █ █
209
+
███ ██ █ ██ █ █ █████ ██████ █ ██████ ██ █ ██ █ ██ ███ █ █ █ █ ███ ██ ████ ██ █
210
+
█ ███ █ █████ █ █ ███ ██ ██ ██ ███ █ █ █ █ █ ████ █ ████ █ ██ █ █ ██
211
+
█ ████ ███ █ █ ████ █ █ ██ ███ █ ██ █ █ ██ █ █ ██ █ █ ██ ██ █████ █ █ ███ █ ████
212
+
█ ██ ██ ██ ██ █ █ ██ ███ ████ ███ ████ █ ██ █ █ ███ ███ ██████ █████ ███ ████ █
213
+
██ █ ███ █ █ ███ █ ██ ███ █ ██ █████ █ ███ █ █ ██ █ █ █ ████ ██ ██ ███ █ █ █ ██
214
+
█ ███ ███ ███ ██ █ ███ █ ████ ██ █ █ ███ █ ██ ██████ █ █ ███ █ ██ ██ ███ ██ █ █
215
+
█ █ █ █ █ █ █ █ █ █ ██ █ █ ███ ███ █ █ █████ █ █ █ █ █ █ █ █ ██ ██ █ ██ █
216
+
█ ██ █ █ ██ ██████ █ █ █ ██ █ █ ██ █ ███ █ █ █ ██ ██ █ █ ███████
217
+
██ ██ █ █ █ █ █ ██████ ██ ████ █ █ █ ██ █ █ █ █ ███ █ ███ █ █ █ ██ ███
218
+
█ ████ █ ██ ██ ███ █ ██ █ ██ ████ █ █ ██ █ █ █ ███ █ ██ ██ ████ ███
219
+
█ ██ ██ █ █ █ █ ███ ██ █ ████ ████ ███ ██ ██ ██ ███ █ ██████
220
+
███ ███ ██ █ █ ██ ██ █ ██ █ █ █ █ ███ █ ███ █ ██ ███ █ █████ ███ ███ ████ █ █ ██
221
+
██ █ █ ████ █ █ ███ ██ █████ █ █ ██ █ █ ██ ██ █ ███ █ █ █ █ █ █ ██ █ ██ ██
222
+
███ █████ ██ ██ █ ███ █ █ ███ ████ ██ █ █████ ██ █ ██ ████ █ █ █
223
+
███ █ █ ███ █ ██ █ █████ █ ██ ████████ ██ ████ █ ████████ █ ███ █ ████ █ █
224
+
█ █ ██ █ ██ █ █ █ ██ ██ █ ██ █ ██ █ █ ██ ██ ██ █ ██ ███ ███ █ ██ ███
225
+
█ ███ ██ █ █ ███ ███ ██ ██ █ █ █ █ █ ███ █ ██ ██ █ █ ███████ █ ███ ███
226
+
██ █ █ █ █ ████ ██ █ █████ ██████ █ █ █ █ █ ██ █ █ ███ █ █ █ █ ██
227
+
█ █ █ █ ████ ██ ██ █ █ █ ███ █ █ █ ██ █ █ ██ █ ██ █ █ █ ██ █ ███ █ ███ ██
228
+
██ █ █ ██ ██ █ █ █ █ ███ █ ██ █ ██ █ █ █ █ ██ ██ ███ ██ ███ ██ ██████ ███
229
+
██ █ █ █ █ █ ███ ███ ████ ██ ██ ███ █ █ ████ █ ███ █ ██ ██ █ █ ███ ███ █ █ █ ███ █
230
+
██ ████ ██ █ █ █ █ █ ██ ██████ ██ █ █ █ █ █ █ █ █ ██ █ █ ████████ █
231
+
████ ██ █ █ ████ █ █ ██ █ █ █ █ ██ █ █ █ ████ █ █████ ███ ██ █ ████ ██ ███ █ █ █ █████
232
+
233
+
>
234
+
```
235
+
236
+
## Task 1
237
+
238
+
```elixir
239
+
img
240
+
|> Day20.enchance(alg)
241
+
|> Day20.enchance(alg)
242
+
|> Day20.Image.lighted()
243
+
```
244
+
245
+
```output
246
+
5179
247
+
```
248
+
249
+
## Task 2
250
+
251
+
```elixir
252
+
1..50
253
+
|> Enum.reduce(img, fn _, acc -> Day20.enchance(acc, alg) end)
254
+
|> Day20.Image.lighted()
255
+
```
256
+
257
+
```output
258
+
16112
259
+
```
+102
2021/day20.txt
+102
2021/day20.txt
···
1
+
####...###.###.##.##.##..###..##.#.##.#...####..##...#..#..#....#..#..##.##..#.#.####.######.#..#.##..##....#.####.##...#.#..#.####.#.#.#..###.##..#.#.#.#...#.....###.#.#...#..#....#######....#..#...###.##.........#.#.##.#........##...#..##.......####.#.#.#.#.#.####..#..........#.##......##......###.#..##.#.#.....###.#..#...###.##........#..#.##.#.###.#..#####..##..#..#.#.#...###..##..#.###.##...#.##.#.....#.#..........#..##.#########.#.#..##.#.##..######.....####...###..###.#..##########.#.#.....###.##.##.
2
+
3
+
#.#...#..##..########...##....#.#.###.#.##.##...#..###.#.##.#.#..#..##..###....#..##.##....#...##.#.
4
+
.###.#..#.#.#..##.##.#.####..##.#...#.###...#.#....#.#.###..#.#..###...##..######..#..#..#####......
5
+
##.#.###.#.#..###...##..###.#.#..#....#...#..#.....##..###.###.######.####.#.#...##.#.##.####..#.##.
6
+
...#..##...########.##..#..#...#...#...##.#..#.#..#.##..##.#..#...#.##........#.#.#.######..#..#.#..
7
+
.....###....#.##....####..#.#.#.###.###.##.#.#.###..#..##.#...##.###..#.##..##.##..#.#....####..#.#.
8
+
..####..###.#..###.#.....#..#..#....#########.####.#..#.##.##..#....#.....#.#.#..#.#..#..###.##...##
9
+
###.#..#####...####.##...####...#.#####.##...##.####.###...###...##...#..#.#.######.##....#....##..#
10
+
...#...#.#.###..#.#..#.#.####..####.#..#...#...#.#...#...#.....##..#.....#.#.#....#####.##..#.#..###
11
+
##...##..###..#..#...#..#..#.####...#.##.###.#.#....#..##....#.....#.##.###.###.#.....#####.#...#...
12
+
.##.#..#..#..#.##.#.##.###.###....##.#.#...#####.#..##..#....###..#.#...##.###.#..#.####..##..######
13
+
#.#..####.###.#####.###.##....##..####.##.##.#########.........#.#.....####.##.....#.#...##.#....##.
14
+
.#..#.#.#..#.#.#.#.#..###....##.#.##.#....#.##.#....#####.#..###...##......#..#.#.##..##..######..##
15
+
..##.####.##.....#.#######..##.##...##.####.####.##...####..#.###....#..###..##..#.####....###..##..
16
+
#.#....#...#.#.#..#.#..#...#####..#.#..###.#.##...#####.....##.#....#.#.##.#..#.#..###...#.#.#..#..#
17
+
##.#.#..#.###.###.##.####....###.#.##.#.#.##...###.##.#.#...##.#.##..#.##.##.#.#....#.....#.#.###...
18
+
.#.##.#....#.#.#.###.##..#######.###..#...#...#####.###.#.#.###..###...###.######.#.#....#...#####.#
19
+
####..#..####.#......####..##...####...##.#.######.###.###.#.#.#.#....##.#######....##.#..####..##.#
20
+
..##.#..###...##....##.###.#.#.#....#..##..###..##..##..#.####..#....#.#.####..#..##.#..#....#..##.#
21
+
.#..#.#..##.###....#...####...##.##..#.#..##.##.##.###....##...##.....#.###......###..#.#..###....#.
22
+
###.#...#.##...####.#.##.###..#.....##.#.#...#.#..###.##..###.#..#.#.#.#.#####.#.####.##..####..##..
23
+
.....#.#..#.##...#..#.....#.###.##########.##.....#..####.##.##.###.##..#.##..#....#.#..##...###.#..
24
+
#..#.##.#.#.#..#....##########.###..#.#...#.##...#####..#..##..#..####.......###..#..#.###..###.##.#
25
+
###.#..##..##..####...#.####..##.######....#..#...#..##...#####.####.##.####...######..#..##...##..#
26
+
..##.#####...#.##..###...###.#......#.#.######.#...####.####.##.##....##..##.#.#..####.#####.######.
27
+
..##..#.#..###..#.....####..#.####.##.#.####.##.....####..##..#...###.#...###...#.#.#........##...#.
28
+
.#.###.##.##.#.##.##..#.#.###...##..#..#..#.##.#.#..##.#.#.#.##....##....#.#......#....#..#....##.#.
29
+
#####.#.###...###.#..#.##.###...###.##.##........#.###.#...##.###.#...###.##.##..#.##.###..####.###.
30
+
#....####.#..#.###....##.#.##..##.....#..#...#...##.#..#.#...#..##.#..##..######.##..####.##...#.#..
31
+
..#.#..#..##.##...##.###...#...###..#.##..#.#####..#.#.##.#######.##.#.#..##..####.....#####..#.#.##
32
+
#.#.....#.#.##.##.##.##......#...##.##.###..#...#.#........##....#.#.....#.##.###....#..###..#..#.##
33
+
..#.#.####..#.##...#.###.##....#.##.#########.###...##...##.#.#....#...#...##.....###.##.........#..
34
+
###.##.#.#...#...##...##...##.##.#..#.#....##.#.##..#..##.#.##.##..#.#.####.###.#.##.##....#.###.##.
35
+
###..#.######.#.###.##.###..##.#..######..###.....###......#.##..##..#.....##..##.##..#.#....##.##.#
36
+
..##.#....#.........##.##.#.#..####..##.#......#....#...##.#####..##........##....#.###...###.###..#
37
+
##...###.#.#..#.#..##.#.##.####....###....##.#####.##....#.##...##..#.....#....#...######..#.#...###
38
+
.##.##.#..###.#.###.#.#.###...####.##.#.#.#.####.#...####.##..###.#...##..##.####..###.#.#..##..##..
39
+
#..#...#####.##...#...##..###.#.#....#.#...#########..##.....##.#.#...###......#.##.########..#.##..
40
+
##..##.##.......##..##........###.#....#.####.#..#.#.###....#.#.#.#.###.#.#..##..##...##.#.....#....
41
+
....#..##...#####...##..#.###....##.##..##.#....#....#..#.#...#.#####...#..##.#.##...#.#...####...##
42
+
..##..####.##....#.###.####...###.#.##.##...#..##..#.###.###.#.#.######.#..#####......##..#.###.#.#.
43
+
#..#.#....#...###.#.#....##.###..#....##..####.#..#.#####.#.###.######...#..###.##..####.#...##.#..#
44
+
..#.##.##.#.##........#..##.....#.#.#.#.##.##..#..##...#.##...#...#.##.###..###.....##..#....#.#..##
45
+
###.##...##.#.#...##...####.###.#...####..###...#.##.#..#.#.###......#.#...###..#.####.##.#.#.####..
46
+
#.#.##.##...#..##..#....#.##..##......###..###...####..##...###.#.##.##..##...####.#.....#.##.##...#
47
+
.....#...#.##.#..#.##.#.####.#######......##.#..#...##..#...#.###.###.#.##.#.##..#.##.##.#..#.###..#
48
+
####...#####..##....##.#####...#...#...##.....##..###..#...###..#...#...##.###..###.#####...##.#....
49
+
#..###...###....#.#.#.######.###..####..#####...###..###..###....##.#.##..#.##..##..#.###.#####.....
50
+
#.#.##.#.####..#####.###.#..#####.#..#.#.#..#.##....##.#.#.#.#.###.###..###...#####.#.##.#.#.#..#...
51
+
.#.#...#..#.##.#..####..###.#..#.########.####......#...##..#####..#...#.#..###..#.#....####....#..#
52
+
##.###.###..#..##.#..#...#..####..#.###..##....#.#...######.##....##...#....#.........####.#.###.#..
53
+
.##..####.##.#.#..####...#.##..##.##..###...#.....##...#......#....##...#####..#####.#.#.#...#..##..
54
+
.#...##.#.###.#.#.##....###..###.##.#.##.....###.####.......#.#.#.#....##.#..#..#..#####..#....#.#.#
55
+
..#.##.###.###.................###.#...#...#.##.#.###..###..#..##..#.#..###..##.#.##.#.##.##.##.#...
56
+
###.#...#..#...###.......###.#.#..#####.####.#..#...##...#####..#........###.#..#.#######..####.#.##
57
+
...#.##.#####.#...##.###...##.#..#..##.##.##..#.#.#.#.###...#.##..#.##.##.#.#.##...##.###....#..#.##
58
+
##.#.####.##.#..#####.#.#...######.###.#.#.##.##...##.#.##.#..#...##.##.#..#...#..#..#..#..#.##.#...
59
+
#.#######.#..#.##..#..#.#..#..####....#.#..#..#...#.....####...#..#.......#..#...##..##.##.##..#.#..
60
+
..##.#.####.#.#.#......########..#..#.....###.#.####.#..#####.##..####.#.###....##.#.#..#.##..#####.
61
+
.##.#.##.#.#..#.#.#.#...#########...#####..#...###.#.##..##.#..##...###.##.#.#.#.#...####.#.#.####.#
62
+
.#####.####..##.##....#.#.#...######.#.#..#.#.#....#.#....##.#..#.###..#..#.####...###..##.#.#.#.#..
63
+
.##..#..###.######.#.#.#..######.##..#..#.######....###.##..#####.....####.#.#.#...##.###.#...##.##.
64
+
.#.####..##.#..#.#..#.###.##.#....##..#.#..#####.##.##...#..####..###..#........#.##..##.####...###.
65
+
..##..###.#.###.#...##.#.##.##.#######..##.#....#.####.#...####...####.###.##.##...##.#..#.#....#..#
66
+
.##..#.######..#.#.##.....######.#####......###.#....###.##.#.###.#..#.#.###.#.####...####.##.....##
67
+
.####....#.##.##.#.#....#.##.#..#...##.....#..##......#..#######..#.##.###.#..#.###.####..###.#.#..#
68
+
..#.##.#.#..##..####....#######.##...#.##.....#.#.##....#.###.#.#..#.###.#.....#.####.#.....##.#...#
69
+
##...#.##..##.#.........#..#..#######.##.#..###.#.###..#.##.#..#...#..#..#.##.##.#..###.###...##.##.
70
+
...#.#..###..#.##.#####.#.##...#.##..###.#...#...#.##....#####..#####....###..#.####.#...#.###.....#
71
+
..#.####..#..#.#..#.######...##.##...##...#.#.#.....#..#...##..#.############.###.####....###..###..
72
+
#.#...#.#.##..##..#.#..#...####.##.##.#.#.#.##..##.#.#.....#....#...#...#.###.#.#####..##.###...#..#
73
+
.#....#.##..###.#..#.###.#..#.#..##..##.......########.#...#...#####.#...#..#..##.....#.##.....####.
74
+
#.#####.#.##.###.#.#....#.#.###...##.#.....##..##..#.#####..#.#.##.#..###..##...#.#.##.#.#.....#.#..
75
+
..###...#.#.......#.#......##.#..#.#.#.#.#...#.###.##...####....######......#...#####..###.##...#..#
76
+
#..#...#..##..#...#...####.#...#....#####.#...#...#.#.....##...##..#...#....#..#####...#.....##...#.
77
+
#.####.#...#...#..##...##....#...#.#.##.##.##...##..##.#..#..#.##.##.##.#.##......#.#...##.....#...#
78
+
.#..####..###........#####...#....#.####..##..#####.##.###..#..###...##..##...##.....#..#.#.###.#...
79
+
.#....#.####....#....##..#.#.######.#######.#.##.###.###...#.#....##..#..####.###.#....###...#.#....
80
+
...###..##.#.##..#.#.#####.######.#..######.##...#.##.#..##.###.#.......#..#...#.###...##..####.##.#
81
+
#....###....#..#####.#..#...###..##.##...##.###...#...#....#..#...#..####.#.####...#..##....#...#.##
82
+
#.####.###...#..#.####...#..#.##.###.#.##.#....#..##.#.#...##.#..#.##.##..#####..#..#...###...#.####
83
+
#.##.##..##.##......#.#.##...###.####.###.####.#...##...#.#...###..###.######.#####....###.####.#...
84
+
##..#.###....#.#..###.#..##..###.#..##..#####.#.###..#.#...##.#.#.#.####....##...##....###.#.#.#..##
85
+
...#.###.###..###.##...#.###.#.####.##..#.#..###...#..##.######.#.#..###..#.##...##.###....##.#...#.
86
+
#..#.#..#.#..#.#.#.#.#..##..#....#..###.###.#...#.#####.#..#..#.#....#.#.#.#....##.##..#...##......#
87
+
...#...##....#....#.##.######.#...#.....#.##..#....#..##.#.........###..#..#..#.##.##...#.#..#######
88
+
##.##..#..#.#..#.#.######.##...####...#...#..#..##.#......#.#....#.###..#.###...#...#...#.##...###..
89
+
#.####.#.##....##..###....#.##.#.##....####.#.#.##.#....#..#..###...#.....##.##....####..###........
90
+
..#..##...##.#...#..#.#..###....##...#...####.....####....###..##..##..##.###..#.....######.........
91
+
.###.###.##.#...#.##..##.#.##.#.#..#.#..###.#....###.#..##.###....#...#####.###..###.####..#.#...##.
92
+
..##.#.#.####.#..#..###.##.#####.#.#....##..#.#.##..##..#...###.#...#...#...#...#..#..##.#...##...##
93
+
......###..#####...##..##.#.....###.#...#..###..####..##..#..#####..##..#..##..####.#..#.........#..
94
+
###............#.#.......###..#..##..#.#####.#.##.########.##..####.#.########..#.###.....#.####.#.#
95
+
.#.....#....##..#.##..#...#.#.##.##..#.##...#.##.#..#......##.....##..##.#..##.###...###....#.##.###
96
+
..#...###....##....#.#...###.###..##.##...#.#.#.#..#....###.#.##.....##.#..#.#######.#.###...###....
97
+
##.#.#.#.#...####.##..#.#####..######..#.#...#.#.........#....##.....#....#.###....#.#.#..#...##....
98
+
.......#.#.#..#....####.##.##.#.......#.#.###..#..#..#..##.#.#.##.#.##.#.#.#..##.#..###..#.###...##.
99
+
..##.#.#..##.##...#..#..#..#..###..#.##..#.##..#..#....#....#.##.##.###.##.###..##.......######.###.
100
+
##.#.#.#.#.#..###...###..####...##..##.###.#..#..####.#...###..#.##.##.#.#.###..###.#.#.#...###..#..
101
+
..##...####......##..#..#..#...#...#..##...######.##......#.#.#....#.#.#.#..#..##.#...#.########...#
102
+
####.##.#.#.####..#.#.##.#..#...#.#.##.#....#..#.####.#.#####.###..##.#.####...##.###.#.#....#.#####
+95
2021/day21.livemd
+95
2021/day21.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 21
4
+
5
+
## Section
6
+
7
+
```elixir
8
+
input = File.read!("day21.txt")
9
+
10
+
[[_, p1], [_, p2]] = Regex.scan(~r/: (\d)/, input)
11
+
12
+
p1 = String.to_integer(p1)
13
+
p2 = String.to_integer(p2)
14
+
15
+
{p1, p2}
16
+
```
17
+
18
+
```output
19
+
{3, 5}
20
+
```
21
+
22
+
```elixir
23
+
round =
24
+
Stream.unfold(0, &{&1, &1 + 1})
25
+
|> Stream.scan({{0, p1}, {0, p2}}, fn n, {{s, p}, other} ->
26
+
p = rem(p - 1 + 6 + n * 9, 10) + 1
27
+
28
+
{other, {s + p, p}}
29
+
end)
30
+
|> Enum.take_while(fn {{s, _}, {_, _}} -> s < 1000 end)
31
+
32
+
{rounds, {{loser, _}, _}} = {length(round), List.last(round)}
33
+
34
+
rounds * 3 * loser
35
+
```
36
+
37
+
```output
38
+
720750
39
+
```
40
+
41
+
```elixir
42
+
defmodule Day21.Task2 do
43
+
def play(p1, p2) do
44
+
tid = :ets.new(__MODULE__, [])
45
+
{a, b} = cached_round({p1 - 1, 0}, {p2 - 1, 0}, tid)
46
+
:ets.delete(tid)
47
+
max(a, b)
48
+
end
49
+
50
+
defp cached_round(a, b, tid) do
51
+
case :ets.lookup(tid, {a, b}) do
52
+
[{_, v}] ->
53
+
v
54
+
55
+
[] ->
56
+
value = round(a, b, tid)
57
+
58
+
:ets.insert(tid, {{a, b}, value})
59
+
60
+
value
61
+
end
62
+
end
63
+
64
+
defp round({_, s}, _, _) when s >= 21, do: {1, 0}
65
+
defp round(_, {_, s}, _) when s >= 21, do: {0, 1}
66
+
67
+
defp round({pos, score}, p2, tid) do
68
+
for a <- 1..3, b <- 1..3, c <- 1..3, reduce: {0, 0} do
69
+
{wins1, wins2} ->
70
+
next = rem(pos + a + b + c, 10)
71
+
72
+
{nscore2, nscore1} =
73
+
cached_round(
74
+
p2,
75
+
{next, score + next + 1},
76
+
tid
77
+
)
78
+
79
+
{wins1 + nscore1, wins2 + nscore2}
80
+
end
81
+
end
82
+
end
83
+
```
84
+
85
+
```output
86
+
{:module, Day21.Task2, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:round, 3}}
87
+
```
88
+
89
+
```elixir
90
+
Day21.Task2.play(p1, p2)
91
+
```
92
+
93
+
```output
94
+
275067741811212
95
+
```
+165
2021/day22.livemd
+165
2021/day22.livemd
···
1
+
<!-- livebook:{"persist_outputs":true} -->
2
+
3
+
# Day 22
4
+
5
+
## Input
6
+
7
+
```elixir
8
+
input =
9
+
File.stream!("day22.txt")
10
+
|> Stream.map(&String.trim/1)
11
+
|> Stream.map(&String.split(&1, [" "]))
12
+
|> Enum.map(fn [action, rest] ->
13
+
{_, bindings} =
14
+
rest
15
+
|> String.replace(",", ";")
16
+
|> Code.eval_string()
17
+
18
+
{String.to_atom(action), Map.new(bindings)}
19
+
end)
20
+
```
21
+
22
+
```output
23
+
[
24
+
on: %{x: -40..7, y: -3..49, z: -48..6},
25
+
on: %{x: -38..10, y: -11..37, z: -30..19},
26
+
on: %{x: -43..1, y: -16..30, z: -38..13},
27
+
on: %{x: -10..44, y: -8..46, z: -41..4},
28
+
on: %{x: -27..19, y: -2..45, z: -33..12},
29
+
on: %{x: -41..4, y: -18..32, z: -34..19},
30
+
on: %{x: -43..9, y: -20..27, z: -34..20},
31
+
on: %{x: -47..-2, y: -5..49, z: -20..32},
32
+
on: %{x: -20..33, y: -40..6, z: -16..33},
33
+
on: %{x: -25..24, y: -47..-2, z: -46..6},
34
+
off: %{x: -28..-9, y: -6..4, z: 22..37},
35
+
on: %{x: -34..14, y: -16..32, z: -43..3},
36
+
off: %{x: -36..-18, y: -44..-33, z: 5..16},
37
+
on: %{x: -23..22, y: -34..11, z: -38..12},
38
+
off: %{x: -24..-15, y: 26..39, z: -18..-9},
39
+
on: %{x: -23..22, y: -31..20, z: -38..13},
40
+
off: %{x: -16..-6, y: 7..19, z: -44..-30},
41
+
on: %{x: -8..45, y: -18..28, z: -27..18},
42
+
off: %{x: -24..-8, y: -3..7, z: 33..45},
43
+
on: %{x: -28..18, y: -15..39, z: -18..35},
44
+
on: %{x: 52706..68579, y: -51721..-24984, z: -29134..-4745},
45
+
on: %{x: 19158..43390, y: 48482..62915, z: 36278..51760},
46
+
on: %{x: 33529..54535, y: 41410..44729, z: 35536..62066},
47
+
on: %{x: 39279..54831, y: -54196..-35294, z: -46321..-19146},
48
+
on: %{x: -49951..-33034, y: -75783..-65241, z: -32974..-9141},
49
+
on: %{x: 16267..33862, y: 32962..38520, z: 55102..80003},
50
+
on: %{x: 28231..33305, y: -13203..11551, z: -82121..-71765},
51
+
on: %{x: -3880..15012, y: -97354..-71276, z: -32509..-10704},
52
+
on: %{x: -59644..-43923, y: -56932..-39976, z: -46680..-24924},
53
+
on: %{x: -22171..6559, y: 59909..65127, z: 51012..71854},
54
+
on: %{x: -35278..-11377, y: -90913..-54535, z: 15441..29860},
55
+
on: %{x: 42440..47504, y: -77130..-54916, z: -5117..22780},
56
+
on: %{x: -23382..-925, y: -96268..-67199, z: -1408..16864},
57
+
on: %{x: 46073..66555, y: 2178..6843, z: -72379..-46993},
58
+
on: %{x: -7367..16256, y: 27822..35444, z: -81222..-57262},
59
+
on: %{x: 70121..85076, y: -2405..20765, z: -25162..-6383},
60
+
on: %{x: -38188..-8731, y: 303..24311, z: -85237..-74901},
61
+
on: %{x: 9308..35679, y: 72560..89334, z: -12862..6802},
62
+
on: %{x: 19088..20550, y: -54261..-29941, z: -66813..-56094},
63
+
on: %{x: 58563..67361, y: 32116..50251, z: -40547..-22471},
64
+
on: %{x: 63946..72885, y: -45525..-32975, z: 6297..33150},
65
+
on: %{x: 35523..45582, y: -46123..-39187, z: -62601..-55854},
66
+
on: %{x: -45263..-16076, y: 66141..71305, z: 24152..51511},
67
+
on: %{x: -56833..-39277, y: -61785..-39127, z: 20400..30866},
68
+
on: %{x: -64099..-47168, y: -14802..-10218, z: 59578..78286},
69
+
on: %{x: 54485..79540, y: -9884..13564, z: -33614..-29502},
70
+
on: %{x: -56136..-41543, y: 40175..50868, z: 18766..46233},
71
+
on: %{x: -29888..-22443, y: 56778..79471, ...},
72
+
on: %{x: 57940..83198, ...},
73
+
on: %{...},
74
+
...
75
+
]
76
+
```
77
+
78
+
## Implementation
79
+
80
+
```elixir
81
+
defmodule Day22 do
82
+
def volume(%{x: x, y: y, z: z}),
83
+
do: Range.size(x) * Range.size(y) * Range.size(z)
84
+
85
+
def volume(list), do: list |> Enum.map(&volume/1) |> Enum.sum()
86
+
87
+
def apply({action, new}, cuboids) do
88
+
cuboids = Enum.flat_map(cuboids, fn old -> sub(old, new) end)
89
+
90
+
case action do
91
+
:on -> [new | cuboids]
92
+
:off -> cuboids
93
+
end
94
+
end
95
+
96
+
defp sub(%{x: ax, y: ay, z: az} = a, %{x: bx, y: by, z: bz} = b) do
97
+
if overlap?(a, b) do
98
+
rx = split(ax, bx)
99
+
ry = split(ay, by)
100
+
rz = split(az, bz)
101
+
102
+
for x <- rx,
103
+
y <- ry,
104
+
z <- rz,
105
+
cube = cube(x, y, z),
106
+
overlap?(cube, a),
107
+
not overlap?(cube, b),
108
+
do: cube
109
+
else
110
+
[a]
111
+
end
112
+
end
113
+
114
+
defp overlap?(%{x: ax, y: ay, z: az}, %{x: bx, y: by, z: bz}) do
115
+
not (Range.disjoint?(ax, bx) or
116
+
Range.disjoint?(ay, by) or
117
+
Range.disjoint?(az, bz))
118
+
end
119
+
120
+
defp cube(x, y, z), do: %{x: x, y: y, z: z}
121
+
122
+
# `b` is "whithin" `a`
123
+
defp split(a1..a2, b1..b2) do
124
+
[
125
+
a1..(b1 - 1)//1,
126
+
max(a1, b1)..min(a2, b2)//1,
127
+
(min(a2, b2) + 1)..a2//1
128
+
]
129
+
|> Enum.reject(&(Range.size(&1) == 0))
130
+
end
131
+
end
132
+
```
133
+
134
+
```output
135
+
{:module, Day22, <<70, 79, 82, 49, 0, 0, 18, ...>>, {:split, 2}}
136
+
```
137
+
138
+
## Task 1
139
+
140
+
```elixir
141
+
range = -50..50
142
+
143
+
input
144
+
|> Enum.reject(fn {_, v} ->
145
+
Enum.any?(Map.values(v), &Range.disjoint?(&1, range))
146
+
end)
147
+
|> Enum.reduce([], &Day22.apply/2)
148
+
|> Day22.volume()
149
+
```
150
+
151
+
```output
152
+
556501
153
+
```
154
+
155
+
## Task 2
156
+
157
+
```elixir
158
+
input
159
+
|> Enum.reduce([], &Day22.apply/2)
160
+
|> Day22.volume()
161
+
```
162
+
163
+
```output
164
+
1217140271559773
165
+
```
+420
2021/day22.txt
+420
2021/day22.txt
···
1
+
on x=-40..7,y=-3..49,z=-48..6
2
+
on x=-38..10,y=-11..37,z=-30..19
3
+
on x=-43..1,y=-16..30,z=-38..13
4
+
on x=-10..44,y=-8..46,z=-41..4
5
+
on x=-27..19,y=-2..45,z=-33..12
6
+
on x=-41..4,y=-18..32,z=-34..19
7
+
on x=-43..9,y=-20..27,z=-34..20
8
+
on x=-47..-2,y=-5..49,z=-20..32
9
+
on x=-20..33,y=-40..6,z=-16..33
10
+
on x=-25..24,y=-47..-2,z=-46..6
11
+
off x=-28..-9,y=-6..4,z=22..37
12
+
on x=-34..14,y=-16..32,z=-43..3
13
+
off x=-36..-18,y=-44..-33,z=5..16
14
+
on x=-23..22,y=-34..11,z=-38..12
15
+
off x=-24..-15,y=26..39,z=-18..-9
16
+
on x=-23..22,y=-31..20,z=-38..13
17
+
off x=-16..-6,y=7..19,z=-44..-30
18
+
on x=-8..45,y=-18..28,z=-27..18
19
+
off x=-24..-8,y=-3..7,z=33..45
20
+
on x=-28..18,y=-15..39,z=-18..35
21
+
on x=52706..68579,y=-51721..-24984,z=-29134..-4745
22
+
on x=19158..43390,y=48482..62915,z=36278..51760
23
+
on x=33529..54535,y=41410..44729,z=35536..62066
24
+
on x=39279..54831,y=-54196..-35294,z=-46321..-19146
25
+
on x=-49951..-33034,y=-75783..-65241,z=-32974..-9141
26
+
on x=16267..33862,y=32962..38520,z=55102..80003
27
+
on x=28231..33305,y=-13203..11551,z=-82121..-71765
28
+
on x=-3880..15012,y=-97354..-71276,z=-32509..-10704
29
+
on x=-59644..-43923,y=-56932..-39976,z=-46680..-24924
30
+
on x=-22171..6559,y=59909..65127,z=51012..71854
31
+
on x=-35278..-11377,y=-90913..-54535,z=15441..29860
32
+
on x=42440..47504,y=-77130..-54916,z=-5117..22780
33
+
on x=-23382..-925,y=-96268..-67199,z=-1408..16864
34
+
on x=46073..66555,y=2178..6843,z=-72379..-46993
35
+
on x=-7367..16256,y=27822..35444,z=-81222..-57262
36
+
on x=70121..85076,y=-2405..20765,z=-25162..-6383
37
+
on x=-38188..-8731,y=303..24311,z=-85237..-74901
38
+
on x=9308..35679,y=72560..89334,z=-12862..6802
39
+
on x=19088..20550,y=-54261..-29941,z=-66813..-56094
40
+
on x=58563..67361,y=32116..50251,z=-40547..-22471
41
+
on x=63946..72885,y=-45525..-32975,z=6297..33150
42
+
on x=35523..45582,y=-46123..-39187,z=-62601..-55854
43
+
on x=-45263..-16076,y=66141..71305,z=24152..51511
44
+
on x=-56833..-39277,y=-61785..-39127,z=20400..30866
45
+
on x=-64099..-47168,y=-14802..-10218,z=59578..78286
46
+
on x=54485..79540,y=-9884..13564,z=-33614..-29502
47
+
on x=-56136..-41543,y=40175..50868,z=18766..46233
48
+
on x=-29888..-22443,y=56778..79471,z=19514..30387
49
+
on x=57940..83198,y=4819..24637,z=-36050..-14367
50
+
on x=-35953..-18054,y=-92305..-62464,z=-24944..433
51
+
on x=66547..83499,y=14135..24578,z=33083..41247
52
+
on x=23558..38387,y=64415..73072,z=-28114..-14640
53
+
on x=-13398..25438,y=-78327..-54021,z=32535..47622
54
+
on x=59279..70463,y=-48832..-12639,z=18768..30270
55
+
on x=-34289..-32327,y=35546..59245,z=55554..73170
56
+
on x=15715..29890,y=-84334..-64420,z=12788..32323
57
+
on x=-38593..-17951,y=-24585..-12831,z=-84437..-70981
58
+
on x=-81422..-51852,y=-44476..-32475,z=-32716..-22730
59
+
on x=-5856..25405,y=22130..39071,z=-84393..-56966
60
+
on x=5807..22366,y=-82846..-62290,z=17828..22587
61
+
on x=40912..63282,y=7257..37789,z=-67351..-34269
62
+
on x=-60312..-52700,y=17308..35727,z=32687..57593
63
+
on x=10748..21594,y=33001..48676,z=-71306..-63061
64
+
on x=-67665..-47017,y=-76167..-51735,z=-13297..-8021
65
+
on x=3312..26580,y=-35665..1379,z=-82617..-69610
66
+
on x=35278..52989,y=25977..48545,z=55789..71242
67
+
on x=17649..50914,y=-77065..-64303,z=-32515..-3058
68
+
on x=55174..70296,y=-63489..-51834,z=-20117..3614
69
+
on x=21633..36099,y=-56734..-43497,z=42283..51140
70
+
on x=32220..54369,y=48382..79084,z=-38669..-15641
71
+
on x=-41133..-21130,y=-43943..-12508,z=-72464..-67577
72
+
on x=1841..14519,y=34565..69226,z=58731..72943
73
+
on x=-81410..-71020,y=-41070..-11211,z=-25653..-2929
74
+
on x=54878..79738,y=37397..60247,z=-29325..-413
75
+
on x=-60358..-43018,y=-65054..-60356,z=991..20784
76
+
on x=-73582..-57508,y=31733..47988,z=-185..25415
77
+
on x=-8304..-1150,y=-81827..-65189,z=31671..57958
78
+
on x=-76108..-70108,y=20214..27537,z=-16291..3825
79
+
on x=15838..47053,y=-82389..-54043,z=3683..28928
80
+
on x=33142..48892,y=-69396..-53597,z=10868..36599
81
+
on x=-38048..-10804,y=-52011..-36488,z=51368..69373
82
+
on x=-4568..12859,y=-45556..-29570,z=-81370..-56776
83
+
on x=-16514..1528,y=-72602..-60172,z=-49767..-15535
84
+
on x=53082..91975,y=-5166..3133,z=22143..45433
85
+
on x=-88733..-57149,y=-41214..-19757,z=-22443..12286
86
+
on x=46893..68079,y=-50078..-29688,z=-39574..-23241
87
+
on x=-75085..-43624,y=16715..41482,z=-56327..-32898
88
+
on x=-76474..-45397,y=-64897..-52688,z=-20583..9143
89
+
on x=-19957..-2573,y=-59234..-31642,z=-79358..-61082
90
+
on x=26667..54887,y=-48864..-21382,z=47058..75678
91
+
on x=-44122..-16611,y=38155..71045,z=31473..49769
92
+
on x=-33391..-25134,y=-28005..-19241,z=51281..71668
93
+
on x=-87044..-63854,y=-23392..-7146,z=-2434..12126
94
+
on x=-591..19282,y=49600..86073,z=-55053..-37283
95
+
on x=-49830..-25077,y=45107..64739,z=-42830..-39577
96
+
on x=-11624..9796,y=-69135..-58118,z=-60400..-46121
97
+
on x=-45799..-24612,y=-62524..-47519,z=-37426..-28681
98
+
on x=34798..65120,y=26496..42571,z=41925..56566
99
+
on x=66112..68536,y=36258..50828,z=-1591..13570
100
+
on x=-15520..17879,y=72198..76196,z=23426..37175
101
+
on x=-39470..-24249,y=-82394..-63435,z=-20694..-7322
102
+
on x=-51300..-19607,y=23582..45094,z=49327..75939
103
+
on x=-40352..-26133,y=44295..65777,z=-60202..-38106
104
+
on x=3094..9439,y=-7619..7072,z=-94190..-71205
105
+
on x=70662..76847,y=32659..50544,z=-16957..-5542
106
+
on x=76282..96199,y=-26320..7056,z=-18269..10065
107
+
on x=-76248..-56030,y=23305..44186,z=-27243..-2017
108
+
on x=37045..57820,y=59279..72594,z=-5542..20408
109
+
on x=-44346..-20543,y=-87528..-58656,z=-35428..-2530
110
+
on x=37275..59953,y=-13753..2122,z=-74562..-53204
111
+
on x=52620..86557,y=23965..51715,z=-9509..-3827
112
+
on x=35795..63942,y=-46269..-22225,z=-54424..-31197
113
+
on x=-59544..-33767,y=9103..43984,z=-75618..-48873
114
+
on x=48874..58442,y=-77723..-42490,z=-14491..-11057
115
+
on x=37993..45421,y=60275..85636,z=-30638..4194
116
+
on x=54414..87440,y=7165..14487,z=21373..49667
117
+
on x=-31071..-8516,y=-63048..-54694,z=48010..53504
118
+
on x=37842..60715,y=-72053..-51698,z=-19271..-12587
119
+
on x=-44461..-12953,y=-33140..-19148,z=65167..75808
120
+
on x=-25510..2687,y=-55779..-24569,z=-69951..-46736
121
+
on x=-58173..-28520,y=-54375..-34513,z=-67610..-42556
122
+
on x=49497..80937,y=22263..43733,z=-42858..-17317
123
+
on x=-77801..-62492,y=-18176..-2842,z=16740..31884
124
+
on x=-40193..-19152,y=-32522..2707,z=-79663..-66600
125
+
on x=-50373..-23703,y=-46038..-12247,z=52074..71463
126
+
on x=52388..77469,y=-31867..-443,z=-50390..-36826
127
+
on x=-88034..-68737,y=-23143..-10464,z=-36065..-16663
128
+
on x=-65232..-53363,y=-17477..5073,z=38324..58181
129
+
on x=30925..53428,y=175..8144,z=57953..85443
130
+
on x=-49373..-38200,y=-311..6146,z=-77273..-48532
131
+
on x=32384..60171,y=53267..59287,z=12544..43012
132
+
on x=-48309..-24591,y=69828..73698,z=-21642..-5616
133
+
on x=-28570..-845,y=-24614..-5964,z=75229..91783
134
+
on x=-84432..-51564,y=-17335..-10501,z=-41225..-31395
135
+
on x=26592..43310,y=59225..62145,z=-45690..-22050
136
+
on x=4610..29014,y=65924..77350,z=-42917..-26623
137
+
on x=7145..20907,y=59641..72450,z=33512..51351
138
+
on x=-7362..2555,y=66424..85969,z=-34868..-15252
139
+
on x=-67112..-48950,y=-34742..-29850,z=33549..51770
140
+
on x=5116..24556,y=-77258..-53349,z=-59199..-49610
141
+
on x=-5223..12832,y=-85767..-62154,z=-63137..-25288
142
+
on x=-57402..-38394,y=23575..43849,z=49017..68715
143
+
on x=-5769..-3315,y=39128..68183,z=-71021..-52847
144
+
on x=6932..24244,y=30420..51629,z=55953..65526
145
+
on x=-29541..7458,y=-90145..-57044,z=-35054..-11576
146
+
on x=-10648..7954,y=-52949..-37015,z=51897..84477
147
+
on x=71634..87410,y=-20915..-15029,z=21564..38229
148
+
on x=-45805..-19490,y=-76458..-46791,z=13612..38412
149
+
on x=46952..72024,y=12007..31441,z=-64360..-43961
150
+
on x=-83434..-50243,y=-40251..-12284,z=10710..45032
151
+
on x=-84933..-68979,y=10644..21421,z=18662..43382
152
+
on x=41424..64670,y=49202..67746,z=-3488..24596
153
+
on x=-58317..-38261,y=25020..54489,z=-62333..-35139
154
+
on x=31402..52264,y=-39865..-3557,z=-61229..-45665
155
+
on x=11038..34450,y=-70660..-57200,z=23378..47844
156
+
on x=-61703..-48338,y=28118..53935,z=40276..44980
157
+
on x=-53403..-37172,y=-42771..-24798,z=44461..67302
158
+
on x=-6688..14480,y=75749..99074,z=-5417..6505
159
+
on x=5384..35432,y=-77335..-56400,z=-59871..-33791
160
+
on x=1603..24013,y=59386..75157,z=17493..37220
161
+
on x=16902..40265,y=20481..51075,z=-81132..-52892
162
+
on x=-31160..-5046,y=-92494..-74285,z=8537..12802
163
+
on x=-18183..-13833,y=13153..49953,z=66118..75643
164
+
on x=55672..76342,y=2135..27763,z=-45212..-19364
165
+
on x=35438..68301,y=43753..57908,z=-41226..-18528
166
+
on x=23646..35699,y=-76449..-53997,z=-21377..-14127
167
+
on x=-31654..-19008,y=18663..34709,z=-81288..-51590
168
+
on x=-76966..-59040,y=-46340..-22258,z=-5666..22990
169
+
on x=-31214..-20656,y=12464..42872,z=-86327..-52582
170
+
on x=21093..34180,y=-67130..-31862,z=44205..71945
171
+
on x=-68172..-49487,y=-62236..-47858,z=-31864..-4610
172
+
on x=13353..24199,y=66632..85682,z=-12135..20096
173
+
on x=-74820..-59297,y=-51864..-14460,z=-18528..3692
174
+
on x=-13545..3537,y=63598..83395,z=-31867..528
175
+
on x=-62438..-44176,y=-30526..3969,z=46663..68416
176
+
on x=22083..43728,y=2257..18901,z=54139..77885
177
+
on x=63102..90207,y=-36610..-21973,z=17017..37294
178
+
on x=-25513..-2920,y=-55321..-26346,z=-82595..-58662
179
+
on x=-59282..-47912,y=-22135..4940,z=-76370..-45984
180
+
on x=-46516..-37421,y=-40875..-30419,z=50078..67090
181
+
on x=247..17678,y=59666..73669,z=41161..66030
182
+
on x=41843..59744,y=-66781..-53325,z=-8026..-866
183
+
on x=56442..67337,y=31447..38104,z=15633..26441
184
+
on x=22246..52258,y=-33697..-12636,z=45175..80705
185
+
on x=25597..36312,y=1997..19204,z=-79738..-54986
186
+
on x=-15480..5974,y=-36965..-8946,z=72200..96085
187
+
on x=-44938..-16803,y=14179..37894,z=63576..70737
188
+
on x=-60563..-26278,y=35288..61821,z=28791..43958
189
+
on x=-2781..27047,y=-78181..-60658,z=7115..28869
190
+
on x=10325..34851,y=-48783..-28260,z=-85849..-67966
191
+
on x=-9545..5720,y=-66451..-53654,z=44770..66479
192
+
on x=-58489..-28712,y=44411..67195,z=-58310..-33840
193
+
on x=24722..34486,y=-67833..-40454,z=-67381..-40990
194
+
on x=58610..73788,y=-12225..7126,z=23646..51111
195
+
on x=-37164..-13729,y=62914..77209,z=11097..21143
196
+
on x=50156..70243,y=-47706..-13090,z=-39835..-13351
197
+
on x=76207..92507,y=-24144..7547,z=-2126..5790
198
+
on x=7817..31657,y=-55682..-32888,z=-81159..-52172
199
+
on x=71906..91201,y=12680..26262,z=3440..23272
200
+
on x=-38023..-4461,y=-83735..-46050,z=-56158..-38260
201
+
on x=-29161..-15540,y=-46665..-40319,z=57913..75651
202
+
on x=-21117..-9729,y=-29641..-21318,z=70665..79125
203
+
on x=-87374..-70709,y=-21190..-6753,z=-8554..26648
204
+
on x=18046..42722,y=48725..78913,z=-43262..-35039
205
+
on x=29634..46384,y=48479..70190,z=-54430..-25966
206
+
on x=49482..67130,y=-27612..-5693,z=32204..54616
207
+
on x=-18852..-12914,y=68426..76907,z=-30812..-26331
208
+
on x=31377..37346,y=22930..58293,z=-67913..-49831
209
+
on x=-39598..-27748,y=6896..20187,z=-73733..-67722
210
+
on x=27751..40846,y=44762..73826,z=25432..54560
211
+
on x=67176..86690,y=-29998..-10307,z=-42471..-11162
212
+
on x=-60642..-28188,y=-43985..-29075,z=-70335..-53311
213
+
on x=-23536..-1020,y=61753..77289,z=-65238..-29581
214
+
on x=-75390..-64417,y=5503..30410,z=-42131..-14557
215
+
on x=38542..53411,y=-59214..-34215,z=40608..53343
216
+
on x=-9650..8906,y=-28406..3212,z=-82649..-62885
217
+
on x=-2849..20704,y=-5170..17802,z=-79401..-74877
218
+
on x=-56789..-34867,y=12504..18099,z=-63987..-57513
219
+
on x=-42510..-29442,y=60034..69734,z=30430..48273
220
+
on x=40496..64946,y=5792..10312,z=45679..68128
221
+
off x=36887..57526,y=47538..63530,z=-42985..-28341
222
+
off x=33479..58411,y=-68548..-46527,z=13251..39103
223
+
on x=63072..81417,y=15646..49394,z=21504..45148
224
+
off x=-76216..-61912,y=-30534..-17551,z=-50280..-26222
225
+
off x=25878..59914,y=-64350..-36188,z=27874..39360
226
+
on x=-51496..-46945,y=-5396..29398,z=-78407..-50985
227
+
off x=-68762..-50445,y=33207..52061,z=-42617..-15847
228
+
off x=-45658..-24730,y=-13226..12659,z=57392..77206
229
+
on x=-8068..23761,y=-48399..-28155,z=50498..71412
230
+
on x=16850..27765,y=-77260..-62223,z=-47859..-28554
231
+
on x=-24227..-1152,y=60223..84591,z=-28685..-1888
232
+
on x=-83203..-60907,y=-38213..-1290,z=-19771..-3635
233
+
off x=22050..29566,y=-55088..-28774,z=-82502..-48350
234
+
off x=55602..73932,y=30508..60779,z=-18418..563
235
+
on x=18396..43696,y=48295..65403,z=-50879..-28862
236
+
off x=58964..95810,y=5076..9444,z=-15462..-7722
237
+
off x=65419..97082,y=-12404..4511,z=-19581..3679
238
+
off x=58822..78853,y=-31174..-6818,z=-32926..-19059
239
+
off x=2312..14918,y=-14468..-8421,z=-82159..-63347
240
+
off x=-8615..6715,y=-34749..-9928,z=-85890..-73180
241
+
on x=10021..28727,y=60507..75964,z=-46068..-16944
242
+
on x=47209..85189,y=-33718..-120,z=-50448..-29027
243
+
off x=-69679..-64804,y=-62936..-27943,z=-6028..3121
244
+
on x=11568..38288,y=-77218..-72840,z=-1658..28856
245
+
off x=68949..83664,y=-11073..17816,z=29484..47100
246
+
on x=-42138..-25168,y=22944..40683,z=45644..72158
247
+
off x=-54212..-23198,y=54848..84031,z=-34752..-8583
248
+
off x=-61743..-43915,y=-62636..-51044,z=-40084..-19481
249
+
off x=-58593..-36205,y=-53837..-28785,z=34877..51154
250
+
on x=-29140..-7627,y=-81905..-73121,z=714..9303
251
+
off x=-70736..-46090,y=-53884..-41570,z=-23826..-13883
252
+
on x=64926..88584,y=-32881..-6387,z=18988..43795
253
+
on x=33758..45337,y=-41289..-13923,z=66720..86882
254
+
off x=67177..85594,y=-1270..27149,z=-12298..10562
255
+
on x=-30728..-9677,y=-80101..-71392,z=-7737..6045
256
+
on x=-34058..-11169,y=-84130..-59611,z=-2411..25556
257
+
on x=-82888..-45532,y=-53498..-43399,z=-15466..12569
258
+
on x=53096..73732,y=-31292..-271,z=46937..54564
259
+
off x=58806..72491,y=-35114..-15573,z=-32393..-15887
260
+
on x=-32570..-20445,y=-70056..-55586,z=15130..43528
261
+
off x=8231..26748,y=-52110..-30753,z=-83079..-61762
262
+
on x=-7168..18004,y=-85219..-76351,z=-55..15553
263
+
on x=-48759..-17822,y=56514..81093,z=-17816..-268
264
+
off x=71494..89379,y=-20577..5421,z=-16229..3599
265
+
on x=-74127..-61857,y=-37318..-16386,z=23418..48020
266
+
off x=46250..64727,y=39997..55663,z=-659..22759
267
+
on x=-3747..18906,y=-88542..-51288,z=-50866..-25393
268
+
on x=11967..39179,y=-42409..-27075,z=51760..78913
269
+
off x=32634..54583,y=53351..78683,z=37069..52980
270
+
on x=-45801..-34391,y=6739..35543,z=-80719..-61475
271
+
off x=-59939..-43493,y=-2816..19380,z=43062..76353
272
+
on x=-54552..-45916,y=30463..59717,z=-60676..-40687
273
+
off x=947..37295,y=17259..35699,z=-77711..-57213
274
+
on x=-34155..-16112,y=58205..77747,z=10469..35078
275
+
off x=-41364..-24954,y=-55475..-20679,z=53974..74195
276
+
on x=-5866..6658,y=-10037..4333,z=69763..93051
277
+
off x=40058..68698,y=51027..74309,z=-3345..5414
278
+
on x=-41513..-26098,y=-47848..-29818,z=44033..62222
279
+
off x=-68876..-57248,y=30233..44005,z=21522..38471
280
+
on x=-10503..7050,y=-33479..-26016,z=-81965..-69000
281
+
on x=-63996..-35550,y=23827..38930,z=50227..78098
282
+
on x=-34663..-17363,y=57015..82338,z=-32869..-17105
283
+
on x=30784..51645,y=32138..66808,z=31941..61168
284
+
off x=-3755..2895,y=-64141..-57971,z=36971..58497
285
+
on x=-20087..3384,y=-63838..-35555,z=57392..69703
286
+
on x=-86557..-54970,y=14861..40412,z=27350..36531
287
+
on x=15258..32146,y=26537..42919,z=65823..68594
288
+
off x=13862..42242,y=-84456..-71150,z=-13132..5905
289
+
off x=-42982..-21849,y=-73917..-48154,z=21993..50847
290
+
on x=-29379..-7101,y=29242..38662,z=-79142..-60459
291
+
off x=11546..49500,y=61301..86969,z=-22865..4577
292
+
on x=-48399..-37677,y=60118..82209,z=-25376..-6657
293
+
on x=-57062..-36839,y=-59454..-56603,z=13677..38428
294
+
off x=-34067..-21168,y=-81243..-56765,z=-17444..3822
295
+
off x=44352..64136,y=50950..67304,z=1643..23339
296
+
off x=64615..79759,y=19545..29449,z=-24935..-16190
297
+
off x=25709..39422,y=-76035..-66047,z=-30123..3414
298
+
on x=-66361..-38785,y=-60420..-53479,z=13651..34601
299
+
on x=26547..53719,y=25778..42415,z=-71893..-46470
300
+
off x=35485..64687,y=32129..59334,z=31017..53502
301
+
off x=-27532..-16323,y=42528..53056,z=44767..66976
302
+
off x=-85657..-60092,y=-4500..16282,z=25434..42820
303
+
on x=10591..32952,y=-55737..-51910,z=45939..63149
304
+
off x=37813..46415,y=-23900..-17178,z=-86629..-47985
305
+
on x=-73010..-52678,y=21009..53737,z=11818..30585
306
+
on x=54601..63218,y=-64449..-41296,z=-8460..15915
307
+
on x=-16576..-10827,y=4232..34251,z=-81741..-62897
308
+
on x=67542..81394,y=-5704..24443,z=-36781..-3582
309
+
on x=-10656..21150,y=-13060..12841,z=-92317..-74508
310
+
on x=-64593..-54055,y=38045..53878,z=-46825..-28151
311
+
off x=36627..44665,y=-34351..-5917,z=-85072..-68088
312
+
off x=-23261..-5824,y=-22196..13929,z=57375..80182
313
+
off x=-32414..-14305,y=-83945..-60848,z=-17901..-6229
314
+
off x=-69199..-45106,y=-35361..-11117,z=47106..48416
315
+
on x=-17361..309,y=-87112..-75083,z=-17309..-846
316
+
on x=49576..70268,y=-52965..-28866,z=-33749..-13320
317
+
off x=-84872..-60225,y=21104..41143,z=-33952..253
318
+
off x=25065..53172,y=-74764..-50642,z=-27008..-12427
319
+
on x=5466..28561,y=58871..87353,z=3407..31099
320
+
off x=58159..69905,y=1719..21038,z=-56660..-32952
321
+
on x=49812..75324,y=42397..58595,z=10501..19992
322
+
off x=-28176..-5545,y=-4561..10768,z=66184..83235
323
+
on x=-36512..-16357,y=6529..33157,z=61540..79962
324
+
on x=-76835..-51187,y=23689..47550,z=26996..57187
325
+
on x=15920..39818,y=-73996..-51623,z=-40686..-18624
326
+
on x=74449..92921,y=-30516..-17926,z=6351..21131
327
+
off x=-36036..-18588,y=66163..82239,z=12845..17683
328
+
on x=-58293..-40285,y=41167..63632,z=5699..26703
329
+
off x=55508..80984,y=411..28348,z=45931..48884
330
+
on x=36567..70716,y=-64313..-46937,z=19533..31078
331
+
on x=57973..76789,y=640..32503,z=-46928..-15585
332
+
on x=40700..59637,y=58372..73306,z=-34813..-17979
333
+
on x=-35809..-16448,y=14279..36807,z=59850..75883
334
+
off x=-11980..15927,y=71172..89369,z=27605..44939
335
+
off x=-28383..-12868,y=-49010..-14693,z=67766..71069
336
+
on x=-63520..-57313,y=-65070..-41322,z=7548..28820
337
+
off x=-30097..-9794,y=50203..76545,z=-47190..-22675
338
+
on x=-10027..13876,y=42660..67586,z=-62549..-45351
339
+
off x=-75743..-41761,y=-18063..-8438,z=43896..51143
340
+
on x=-53973..-21852,y=19812..35895,z=-65245..-53623
341
+
on x=9327..30980,y=60724..81052,z=4679..22655
342
+
on x=-9382..14696,y=-12635..-7880,z=-92088..-71928
343
+
on x=-49568..-21303,y=45400..66270,z=-37218..-23585
344
+
on x=26374..50716,y=29522..45024,z=-72113..-50858
345
+
off x=-7123..9906,y=-30606..-21570,z=-89692..-60367
346
+
off x=24645..34685,y=-7385..-535,z=-75457..-69280
347
+
off x=46600..75937,y=42638..62019,z=-15214..-800
348
+
off x=-73156..-64899,y=-18542..6622,z=-51976..-33625
349
+
on x=-46953..-31989,y=-43453..-17942,z=48050..68549
350
+
off x=44491..64439,y=-52270..-47527,z=25565..42399
351
+
on x=54480..85695,y=-56683..-30655,z=-8303..15795
352
+
on x=29997..57709,y=62586..84888,z=-22633..2635
353
+
on x=-56730..-33262,y=-61124..-36167,z=-44900..-31218
354
+
on x=-36099..-17509,y=59225..80566,z=-49431..-28644
355
+
on x=45514..74203,y=-2009..10424,z=-65113..-45173
356
+
off x=-31309..-22150,y=-84143..-63111,z=26691..48979
357
+
off x=-68448..-52444,y=-49282..-47076,z=-6567..21766
358
+
on x=9190..23305,y=-40030..-24391,z=56198..85303
359
+
off x=5498..22227,y=-43923..-15355,z=-85770..-69241
360
+
off x=-61505..-41086,y=34956..58168,z=-43349..-24183
361
+
on x=-458..11929,y=14735..44319,z=60006..73064
362
+
off x=54250..68185,y=-71222..-34674,z=-28518..-15694
363
+
off x=-28528..42,y=-45762..-25317,z=64430..72231
364
+
off x=17184..32440,y=-43934..-25096,z=-75789..-65047
365
+
on x=-54107..-45535,y=-647..29416,z=56621..66738
366
+
on x=-63306..-50383,y=-54815..-51798,z=3488..23514
367
+
off x=-33064..-17821,y=-68795..-40276,z=48722..58281
368
+
off x=28813..45569,y=10091..43242,z=48567..79748
369
+
on x=-34407..-13658,y=-82959..-67725,z=-14721..-7549
370
+
off x=11006..38914,y=-64578..-54646,z=31394..48188
371
+
on x=-89516..-56035,y=-33338..-20011,z=23842..40221
372
+
on x=12382..42662,y=51972..71326,z=-51009..-29545
373
+
on x=-23497..-510,y=-14057..6559,z=-82664..-61835
374
+
off x=42738..44332,y=-45357..-25100,z=44137..62767
375
+
off x=-19799..9546,y=-63709..-45750,z=48687..64170
376
+
off x=-50529..-30472,y=-47930..-19905,z=-75205..-45624
377
+
off x=-23531..14033,y=68487..89564,z=8925..28259
378
+
on x=1663..20113,y=56791..75346,z=12276..44119
379
+
off x=45731..75170,y=-23286..393,z=-64525..-28621
380
+
on x=-78486..-56778,y=-31099..-18591,z=-48346..-25135
381
+
on x=-43514..-34754,y=67709..72495,z=-16374..5180
382
+
off x=32961..61842,y=-62894..-41340,z=-33931..-15049
383
+
on x=-52937..-36075,y=64942..83439,z=-3622..27175
384
+
off x=41640..61376,y=-70913..-50192,z=-23373..-12724
385
+
on x=16109..24715,y=-19443..8667,z=75001..90517
386
+
off x=14880..41615,y=37677..55218,z=-64590..-40070
387
+
off x=-93344..-73236,y=-27796..-24908,z=-10127..16501
388
+
off x=59960..65418,y=-4002..12224,z=-67984..-42193
389
+
on x=42351..56746,y=-20084..-13129,z=-65765..-51230
390
+
off x=-59234..-29355,y=-71438..-58469,z=-11162..7404
391
+
on x=51040..67401,y=-60224..-40198,z=-546..19625
392
+
on x=-77978..-59874,y=36001..58307,z=14976..23796
393
+
off x=56211..75341,y=8311..17708,z=-53749..-20735
394
+
on x=-36432..-7183,y=19575..30346,z=-86318..-58459
395
+
off x=-287..4588,y=-90791..-66459,z=-21768..4012
396
+
off x=-79379..-62831,y=-31440..-593,z=-17403..8089
397
+
off x=-35905..-18333,y=29389..56106,z=42947..70271
398
+
off x=25117..47923,y=3093..37238,z=-77359..-65332
399
+
on x=56769..88321,y=-37074..-5686,z=-21787..-6401
400
+
on x=-28981..-10417,y=28580..52377,z=-77998..-54458
401
+
off x=-24957..-267,y=35439..53345,z=51302..86849
402
+
off x=-47011..-30673,y=-6746..-378,z=65710..79497
403
+
off x=-73026..-58387,y=-27117..-1079,z=-58305..-36042
404
+
off x=-20512..4246,y=45491..71174,z=48277..50414
405
+
on x=23379..43354,y=63961..93513,z=3964..25213
406
+
off x=597..17616,y=-83653..-72150,z=-11879..21798
407
+
off x=-58597..-46587,y=12126..39528,z=-75993..-36792
408
+
on x=-2903..11768,y=72176..88526,z=23687..33143
409
+
on x=12525..24278,y=-2148..6961,z=59625..82181
410
+
on x=-84588..-72500,y=-29471..-14022,z=-16989..13434
411
+
off x=-58154..-34165,y=-74940..-54914,z=12160..19819
412
+
off x=-6724..14627,y=22646..53365,z=-88495..-61533
413
+
on x=-87262..-70236,y=-23648..3813,z=11206..27547
414
+
on x=53546..71522,y=-28908..-8027,z=46725..60604
415
+
on x=-81664..-64558,y=-26054..-6136,z=-43138..-11228
416
+
off x=74496..91204,y=1367..9913,z=-2108..16186
417
+
on x=-69821..-39879,y=-4418..23997,z=-65231..-50478
418
+
off x=6104..33203,y=65171..78461,z=26193..44937
419
+
off x=-4928..16268,y=50554..71798,z=-66020..-34009
420
+
off x=22174..43968,y=-69871..-46557,z=-37898..-23874
+90
2021/day3.livemd
+90
2021/day3.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 3
7
+
8
+
## Input
9
+
10
+
```elixir
11
+
stream =
12
+
File.stream!("day3.txt")
13
+
|> Enum.map(&String.trim/1)
14
+
|> Enum.map(&String.to_charlist/1)
15
+
16
+
defmodule Day3 do
17
+
def count(list) do
18
+
Enum.reduce(list, List.duplicate(0, 12), fn input, acc ->
19
+
for {value, counter} <- Enum.zip(input, acc) do
20
+
case value do
21
+
?1 -> counter + 1
22
+
?0 -> counter
23
+
end
24
+
end
25
+
end)
26
+
end
27
+
end
28
+
```
29
+
30
+
```output
31
+
{:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}}
32
+
```
33
+
34
+
## Task 1
35
+
36
+
```elixir
37
+
half = div(length(stream), 2)
38
+
39
+
{a, b} =
40
+
stream
41
+
|> Day3.count()
42
+
|> Enum.reduce({0, 0}, fn elem, {a, b} ->
43
+
if elem > half do
44
+
{a * 2 + 1, b * 2}
45
+
else
46
+
{a * 2, b * 2 + 1}
47
+
end
48
+
end)
49
+
50
+
a * b
51
+
```
52
+
53
+
```output
54
+
3847100
55
+
```
56
+
57
+
## Task 2
58
+
59
+
```elixir
60
+
defmodule Day3.Task2 do
61
+
def reduce(list, cb), do: reduce(list, 0, cb)
62
+
63
+
defp reduce([elem], _, _), do: elem
64
+
65
+
defp reduce(list, at, cb) do
66
+
counts = Day3.count(list)
67
+
68
+
half = div(length(list), 2)
69
+
count = Enum.at(counts, at)
70
+
71
+
bit =
72
+
cond do
73
+
count == half and cb.(count + 1, half) -> ?1
74
+
count != half and cb.(count, half) -> ?1
75
+
true -> ?0
76
+
end
77
+
78
+
reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb)
79
+
end
80
+
end
81
+
82
+
co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2)
83
+
o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2)
84
+
85
+
co2 * o2
86
+
```
87
+
88
+
```output
89
+
4105235
90
+
```
+126
2021/day4.livemd
+126
2021/day4.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 4
7
+
8
+
## Input
9
+
10
+
This time it is a little bit more convoluted, as there are 2 parts of the input.
11
+
Fortunately we can easily disect the parts via pattern matching.
12
+
13
+
Technically the conversion to the numbers is not needed, but it does no harm
14
+
and provides additional layer of safety against some whitespace characters left there
15
+
and here.
16
+
17
+
The `Day4.win/2` function is manually unrolled, as it is easier to write than some
18
+
random jumping in the list.
19
+
20
+
<!-- livebook:{"disable_formatting":true} -->
21
+
22
+
```elixir
23
+
[numbers | bingos] =
24
+
File.read!("day4.txt")
25
+
|> String.split("\n\n", trim: true)
26
+
27
+
numbers =
28
+
numbers
29
+
|> String.trim()
30
+
|> String.split(",")
31
+
|> Enum.map(&String.to_integer/1)
32
+
33
+
bingos =
34
+
bingos
35
+
|> Enum.map(fn bingo ->
36
+
bingo
37
+
|> String.split(~r/\s+/, trim: true)
38
+
|> Enum.map(&String.to_integer/1)
39
+
end)
40
+
41
+
defmodule Day4 do
42
+
def win(
43
+
[
44
+
a1, a2, a3, a4, a5,
45
+
b1, b2, b3, b4, b5,
46
+
c1, c2, c3, c4, c5,
47
+
d1, d2, d3, d4, d5,
48
+
e1, e2, e3, e4, e5
49
+
],
50
+
nums
51
+
) do
52
+
# Rows
53
+
all_in([a1, a2, a3, a4, a5], nums) or
54
+
all_in([b1, b3, b3, b4, b5], nums) or
55
+
all_in([c1, c2, c3, c4, c5], nums) or
56
+
all_in([d1, d2, d3, d4, d5], nums) or
57
+
all_in([e1, e2, e3, e4, e5], nums) or
58
+
# Columns
59
+
all_in([a1, b1, c1, d1, e1], nums) or
60
+
all_in([a2, b2, c2, d2, e2], nums) or
61
+
all_in([a3, b3, c3, d3, e3], nums) or
62
+
all_in([a4, b4, c4, d4, e4], nums) or
63
+
all_in([a5, b5, c5, d5, e5], nums)
64
+
end
65
+
66
+
def not_matched(bingo, nums) do
67
+
Enum.reject(bingo, &(&1 in nums))
68
+
end
69
+
70
+
defp all_in(list, nums) do
71
+
Enum.all?(list, &(&1 in nums))
72
+
end
73
+
end
74
+
```
75
+
76
+
```output
77
+
{:module, Day4, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:all_in, 2}}
78
+
```
79
+
80
+
## Task 1
81
+
82
+
We simply traverse the `numbers` list aggregating the numbers (order doesn't really matter,
83
+
here we aggregate them in reverse order to speedup the code). When we have enough numbers
84
+
that any of the `bingos` is winning one, then we halt the reduction and return computed
85
+
result.
86
+
87
+
```elixir
88
+
numbers
89
+
|> Enum.reduce_while([], fn elem, acc ->
90
+
matches = [elem | acc]
91
+
92
+
case Enum.find(bingos, &Day4.win(&1, matches)) do
93
+
nil -> {:cont, matches}
94
+
bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
95
+
end
96
+
end)
97
+
```
98
+
99
+
```output
100
+
34506
101
+
```
102
+
103
+
## Task 2
104
+
105
+
```elixir
106
+
numbers
107
+
|> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} ->
108
+
matches = [elem | acc]
109
+
110
+
case bingos do
111
+
[bingo] ->
112
+
if Day4.win(bingo, matches) do
113
+
{:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
114
+
else
115
+
{:cont, {bingos, matches}}
116
+
end
117
+
118
+
_ ->
119
+
{:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}}
120
+
end
121
+
end)
122
+
```
123
+
124
+
```output
125
+
7686
126
+
```
+109
2021/day5.livemd
+109
2021/day5.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 5
7
+
8
+
```elixir
9
+
defmodule Day5 do
10
+
defmodule Point do
11
+
defstruct [:x, :y]
12
+
13
+
def parse(input) do
14
+
[x, y] = String.split(input, ",")
15
+
16
+
%__MODULE__{x: String.to_integer(x), y: String.to_integer(y)}
17
+
end
18
+
end
19
+
20
+
defmodule Line do
21
+
defstruct [:start, :finish]
22
+
23
+
def new(a, b) do
24
+
{start, finish} =
25
+
cond do
26
+
a.x < b.x -> {a, b}
27
+
a.y < b.y -> {a, b}
28
+
true -> {b, a}
29
+
end
30
+
31
+
%__MODULE__{start: start, finish: finish}
32
+
end
33
+
34
+
def horizontal?(a), do: a.start.y == a.finish.y
35
+
def vertical?(a), do: a.start.x == a.finish.x
36
+
37
+
def points(a) do
38
+
case {sign(a.finish.x - a.start.x), sign(a.finish.y - a.start.y)} do
39
+
{0, dy} -> for y <- a.start.y..a.finish.y//dy, do: {a.start.x, y}
40
+
{dx, 0} -> for x <- a.start.x..a.finish.x//dx, do: {x, a.start.y}
41
+
{dx, dy} -> Enum.zip(a.start.x..a.finish.x//dx, a.start.y..a.finish.y//dy)
42
+
end
43
+
end
44
+
45
+
def orientation(a) do
46
+
cond do
47
+
horizontal?(a) -> :horizontal
48
+
vertical?(a) -> :vertical
49
+
true -> :diagonal
50
+
end
51
+
end
52
+
53
+
defp sign(0), do: 0
54
+
defp sign(x) when x < 0, do: -1
55
+
defp sign(x) when x > 0, do: 1
56
+
end
57
+
end
58
+
59
+
lines =
60
+
File.stream!("day5.txt")
61
+
|> Stream.map(&String.trim/1)
62
+
|> Stream.map(fn input ->
63
+
[a, b] = String.split(input, " -> ")
64
+
65
+
pa = Day5.Point.parse(a)
66
+
pb = Day5.Point.parse(b)
67
+
68
+
Day5.Line.new(pa, pb)
69
+
end)
70
+
```
71
+
72
+
```output
73
+
#Stream<[
74
+
enum: %File.Stream{
75
+
line_or_bytes: :line,
76
+
modes: [:raw, :read_ahead, :binary],
77
+
path: "day5.txt",
78
+
raw: true
79
+
},
80
+
funs: [#Function<47.58486609/1 in Stream.map/2>, #Function<47.58486609/1 in Stream.map/2>]
81
+
]>
82
+
```
83
+
84
+
## Task 1
85
+
86
+
```elixir
87
+
lines
88
+
|> Stream.filter(&(Day5.Line.orientation(&1) != :diagonal))
89
+
|> Stream.flat_map(&Day5.Line.points/1)
90
+
|> Enum.frequencies()
91
+
|> Enum.count(fn {_k, v} -> v > 1 end)
92
+
```
93
+
94
+
```output
95
+
5197
96
+
```
97
+
98
+
## Task 2
99
+
100
+
```elixir
101
+
lines
102
+
|> Stream.flat_map(&Day5.Line.points/1)
103
+
|> Enum.frequencies()
104
+
|> Enum.count(fn {_k, v} -> v > 1 end)
105
+
```
106
+
107
+
```output
108
+
18605
109
+
```
+57
2021/day6.livemd
+57
2021/day6.livemd
···
1
+
<!-- vim:ft=markdown -->
2
+
3
+
<!-- livebook:{"persist_outputs":true} -->
4
+
5
+
# Day 6
6
+
7
+
## Section
8
+
9
+
```elixir
10
+
initial = for i <- 0..8, into: %{}, do: {i, 0}
11
+
12
+
counts =
13
+
File.read!("day6.txt")
14
+
|> String.trim()
15
+
|> String.split(",")
16
+
|> Enum.map(&String.to_integer/1)
17
+
|> Enum.frequencies()
18
+
|> Map.merge(initial, fn _, a, _ -> a end)
19
+
20
+
defmodule Day6 do
21
+
def next(%{0 => next} = population) do
22
+
1..8
23
+
|> Map.new(&{&1 - 1, population[&1]})
24
+
|> Map.merge(%{6 => next, 8 => next}, fn _, v1, v2 -> v1 + v2 end)
25
+
end
26
+
end
27
+
```
28
+
29
+
```output
30
+
{:module, Day6, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:next, 1}}
31
+
```
32
+
33
+
## Task 1
34
+
35
+
```elixir
36
+
1..80
37
+
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
38
+
|> Map.values()
39
+
|> Enum.sum()
40
+
```
41
+
42
+
```output
43
+
343441
44
+
```
45
+
46
+
## Task 2
47
+
48
+
```elixir
49
+
1..256
50
+
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
51
+
|> Map.values()
52
+
|> Enum.sum()
53
+
```
54
+
55
+
```output
56
+
1569108373832
57
+
```
+56
2021/day7.livemd
+56
2021/day7.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 7
7
+
8
+
```elixir
9
+
input =
10
+
File.read!("day7.txt")
11
+
|> String.trim()
12
+
|> String.split(",")
13
+
|> Enum.map(&String.to_integer/1)
14
+
```
15
+
16
+
```output
17
+
[1101, 1, 29, 67, 1102, 0, 1, 65, 1008, 65, 35, 66, 1005, 66, 28, 1, 67, 65, 20, 4, 0, 1001, 65, 1,
18
+
65, 1106, 0, 8, 99, 35, 67, 101, 99, 105, 32, 110, 39, 101, 115, 116, 32, 112, 97, 115, 32, 117,
19
+
110, 101, 32, 105, ...]
20
+
```
21
+
22
+
## Task 1
23
+
24
+
```elixir
25
+
median = Enum.at(Enum.sort(input), div(length(input), 2))
26
+
27
+
input
28
+
|> Enum.map(&abs(&1 - median))
29
+
|> Enum.sum()
30
+
```
31
+
32
+
```output
33
+
336721
34
+
```
35
+
36
+
## Task 2
37
+
38
+
```elixir
39
+
arith_sum = fn n -> div(n * n + n, 2) end
40
+
41
+
max = Enum.max(input)
42
+
43
+
mean = Enum.sum(input) / length(input)
44
+
45
+
[floor(mean), ceil(mean)]
46
+
|> Enum.map(fn n ->
47
+
input
48
+
|> Enum.map(&arith_sum.(abs(&1 - n)))
49
+
|> Enum.sum()
50
+
end)
51
+
|> Enum.min()
52
+
```
53
+
54
+
```output
55
+
91638945
56
+
```
+141
2021/day8.livemd
+141
2021/day8.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
# Day 8
7
+
8
+
```elixir
9
+
input =
10
+
File.stream!("day8.txt")
11
+
|> Stream.map(fn line ->
12
+
line
13
+
|> String.split(" | ")
14
+
|> Enum.map(fn part ->
15
+
part
16
+
|> String.trim()
17
+
|> String.split(" ")
18
+
|> Enum.map(fn disp ->
19
+
# Sort characters in each entry to simplify later work
20
+
disp
21
+
|> String.to_charlist()
22
+
|> Enum.sort()
23
+
|> List.to_string()
24
+
end)
25
+
end)
26
+
|> List.to_tuple()
27
+
end)
28
+
```
29
+
30
+
```output
31
+
#Stream<[
32
+
enum: %File.Stream{
33
+
line_or_bytes: :line,
34
+
modes: [:raw, :read_ahead, :binary],
35
+
path: "day8.txt",
36
+
raw: true
37
+
},
38
+
funs: [#Function<47.58486609/1 in Stream.map/2>]
39
+
]>
40
+
```
41
+
42
+
## Task 1
43
+
44
+
We simply need to count all occurences of the values that have 2, 3, 4, or 7 highlighted
45
+
segments.
46
+
47
+
```elixir
48
+
input
49
+
|> Enum.map(fn {_, output} ->
50
+
Enum.count(output, &(byte_size(&1) in [2, 3, 4, 7]))
51
+
end)
52
+
|> Enum.sum()
53
+
```
54
+
55
+
```output
56
+
390
57
+
```
58
+
59
+
## Task 2
60
+
61
+
```elixir
62
+
defmodule Day8.Task2 do
63
+
defp a --- b, do: MapSet.difference(a, b)
64
+
65
+
defp a +++ b, do: MapSet.union(a, b)
66
+
67
+
defp a <~> b, do: MapSet.intersection(a, b)
68
+
69
+
# 1. 7. 4. 2|3|5. 2|3|5. 2|3|5. 6|9|0. 6|9|0. 6|9|0. 8.
70
+
def deduce([cf, acf, bcdf, acdeg, acdfg, abdfg, abdefg, abcdfg, abcefg, abcdefg]) do
71
+
eg = abcdefg --- (acf +++ bcdf)
72
+
bd = bcdf --- cf
73
+
adg = acdeg <~> acdfg <~> abdfg
74
+
abfg = abdefg <~> abcdfg <~> abcefg
75
+
a = acf --- cf
76
+
b = abfg <~> bd
77
+
f = abfg <~> cf
78
+
g = adg <~> eg
79
+
d = adg <~> bd
80
+
c = cf --- f
81
+
e = eg --- g
82
+
83
+
[a, b, c, d, e, f, g] =
84
+
[a, b, c, d, e, f, g]
85
+
|> Enum.map(&extract/1)
86
+
87
+
[
88
+
# 0
89
+
[a, b, c, e, f, g],
90
+
# 1
91
+
[c, f],
92
+
# 2
93
+
[a, c, d, e, g],
94
+
# 3
95
+
[a, c, d, f, g],
96
+
# 4
97
+
[b, c, d, f],
98
+
# 5
99
+
[a, b, d, f, g],
100
+
# 6
101
+
[a, b, d, e, f, g],
102
+
# 7
103
+
[a, c, f],
104
+
# 8
105
+
[a, b, c, d, e, f, g],
106
+
# 9
107
+
[a, b, c, d, f, g]
108
+
]
109
+
|> Enum.map(&List.to_string(Enum.sort(&1)))
110
+
|> Enum.with_index()
111
+
|> Map.new()
112
+
end
113
+
114
+
defp extract(a) do
115
+
# Just additional sanity check
116
+
[v] = MapSet.to_list(a)
117
+
118
+
v
119
+
end
120
+
121
+
def decode(matches, output) do
122
+
output
123
+
|> Enum.map(&matches[&1])
124
+
|> Integer.undigits()
125
+
end
126
+
end
127
+
128
+
input
129
+
|> Enum.map(fn {input, output} ->
130
+
input
131
+
|> Enum.sort_by(&byte_size/1)
132
+
|> Enum.map(&MapSet.new(String.to_charlist(&1)))
133
+
|> Day8.Task2.deduce()
134
+
|> Day8.Task2.decode(output)
135
+
end)
136
+
|> Enum.sum()
137
+
```
138
+
139
+
```output
140
+
1011785
141
+
```
+114
2021/day9.livemd
+114
2021/day9.livemd
···
1
+
<!-- vim:ft=markdown
2
+
-->
3
+
4
+
<!-- livebook:{"persist_outputs":true} -->
5
+
6
+
7
+
# Day 9
8
+
9
+
## Setup
10
+
11
+
```elixir
12
+
Mix.install([
13
+
{:nx, github: "elixir-nx/nx", sparse: "nx"},
14
+
{:kino, github: "livebook-dev/kino"}
15
+
])
16
+
```
17
+
18
+
```output
19
+
:ok
20
+
```
21
+
22
+
## Input
23
+
24
+
```elixir
25
+
input =
26
+
File.read!("day9.txt")
27
+
|> String.split("\n", trim: true)
28
+
|> Enum.map(&String.to_charlist(String.trim(&1)))
29
+
|> Nx.tensor(names: [:y, :x])
30
+
|> Nx.subtract(?0)
31
+
|> Nx.add(1)
32
+
33
+
{width, height} = shape = Nx.shape(input)
34
+
```
35
+
36
+
```output
37
+
{100, 100}
38
+
```
39
+
40
+
## Task 1
41
+
42
+
```elixir
43
+
minima = fn padded, size, axis ->
44
+
shifted = Nx.slice_axis(padded, 0, size, axis)
45
+
x1 = Nx.less(input, shifted)
46
+
47
+
shifted = Nx.slice_axis(padded, 2, size, axis)
48
+
x2 = Nx.less(input, shifted)
49
+
50
+
Nx.logical_and(x1, x2)
51
+
end
52
+
53
+
padded = Nx.pad(input, 99, [{0, 0, 0}, {1, 1, 0}])
54
+
55
+
x = minima.(padded, width, :x)
56
+
57
+
padded = Nx.pad(input, 99, [{1, 1, 0}, {0, 0, 0}])
58
+
59
+
y = minima.(padded, height, :y)
60
+
61
+
minimas = Nx.logical_and(x, y)
62
+
63
+
input
64
+
|> Nx.multiply(minimas)
65
+
|> Nx.sum()
66
+
|> Nx.to_number()
67
+
```
68
+
69
+
```output
70
+
452
71
+
```
72
+
73
+
## Task 2
74
+
75
+
```elixir
76
+
input
77
+
|> Nx.equal(10)
78
+
|> Nx.logical_not()
79
+
|> Nx.select(Nx.iota(shape), 9999)
80
+
|> Nx.to_flat_list()
81
+
|> Enum.reject(&(&1 == 9999))
82
+
|> Enum.map(fn point -> {div(point, width), rem(point, width)} end)
83
+
|> Enum.reduce([], fn {y, x} = point, basins ->
84
+
basin_left = Enum.find_index(basins, &({y, x - 1} in &1))
85
+
basin_up = Enum.find_index(basins, &({y - 1, x} in &1))
86
+
87
+
case {basin_left, basin_up} do
88
+
{nil, nil} ->
89
+
[MapSet.new([point]) | basins]
90
+
91
+
{idx, nil} ->
92
+
List.update_at(basins, idx, &MapSet.put(&1, point))
93
+
94
+
{nil, idx} ->
95
+
List.update_at(basins, idx, &MapSet.put(&1, point))
96
+
97
+
{idx, idx} ->
98
+
List.update_at(basins, idx, &MapSet.put(&1, point))
99
+
100
+
{idx1, idx2} ->
101
+
{old, basins} = List.pop_at(basins, max(idx1, idx2))
102
+
103
+
List.update_at(basins, min(idx1, idx2), &(&1 |> MapSet.union(old) |> MapSet.put(point)))
104
+
end
105
+
end)
106
+
|> Enum.map(&MapSet.size/1)
107
+
|> Enum.sort(:desc)
108
+
|> Enum.take(3)
109
+
|> Enum.reduce(&*/2)
110
+
```
111
+
112
+
```output
113
+
1263735
114
+
```
-1985
2021/solutions.livemd
-1985
2021/solutions.livemd
···
1
-
<!--
2
-
vim:ft=markdown --!>
3
-
livebook:{"persist_outputs":true}
4
-
-->
5
-
6
-
<!-- livebook:{"persist_outputs":true} -->
7
-
8
-
# Advent of Code 2021
9
-
10
-
## Setup
11
-
12
-
```elixir
13
-
Mix.install([
14
-
{:nx, github: "elixir-nx/nx", sparse: "nx"},
15
-
{:kino, github: "livebook-dev/kino"}
16
-
])
17
-
```
18
-
19
-
```output
20
-
:ok
21
-
```
22
-
23
-
## Day 1
24
-
25
-
### Load input
26
-
27
-
```elixir
28
-
stream =
29
-
File.stream!("day1.txt")
30
-
|> Stream.map(&String.to_integer(String.trim(&1)))
31
-
```
32
-
33
-
```output
34
-
#Stream<[
35
-
enum: %File.Stream{
36
-
line_or_bytes: :line,
37
-
modes: [:raw, :read_ahead, :binary],
38
-
path: "day1.txt",
39
-
raw: true
40
-
},
41
-
funs: [#Function<47.58486609/1 in Stream.map/2>]
42
-
]>
43
-
```
44
-
45
-
### Task 1
46
-
47
-
<!-- livebook:{"break_markdown":true} -->
48
-
49
-
Compute count of consecutive increases
50
-
51
-
```elixir
52
-
stream
53
-
|> Stream.chunk_every(2, 1, :discard)
54
-
|> Enum.count(fn [a, b] -> a < b end)
55
-
```
56
-
57
-
```output
58
-
1688
59
-
```
60
-
61
-
### Task 2
62
-
63
-
<!-- livebook:{"break_markdown":true} -->
64
-
65
-
Compute count of consecutive increases of sums of trigrams.
66
-
67
-
However we can notice, that if we have list like:
68
-
69
-
$$
70
-
[a, b, c, d]
71
-
$$
72
-
73
-
Then when we want to compare consecutive trigrams then we compare:
74
-
75
-
$$
76
-
a + b + c < b + c + d \\
77
-
a < d
78
-
$$
79
-
80
-
So we can traverse each 4 elements and then just compare first and last one
81
-
instead of summing and then traversing it again.
82
-
83
-
```elixir
84
-
stream
85
-
|> Stream.chunk_every(4, 1, :discard)
86
-
|> Enum.count(fn [a, _, _, b] -> a < b end)
87
-
```
88
-
89
-
```output
90
-
1728
91
-
```
92
-
93
-
## Day 2
94
-
95
-
### Load input
96
-
97
-
We do parsing there, as it will help us with the latter tasks. Pattern matching
98
-
is the simplest approach there, as input is in form of:
99
-
100
-
```
101
-
forward 10
102
-
up 20
103
-
down 30
104
-
```
105
-
106
-
We need to `trim/1` input to make sure that the last newline will not interrupt
107
-
`String.to_integer/1` calls.
108
-
109
-
```elixir
110
-
stream =
111
-
File.stream!("day2.txt")
112
-
|> Stream.map(fn input ->
113
-
case String.trim(input) do
114
-
"forward " <> n -> {:forward, String.to_integer(n)}
115
-
"up " <> n -> {:up, String.to_integer(n)}
116
-
"down " <> n -> {:down, String.to_integer(n)}
117
-
end
118
-
end)
119
-
```
120
-
121
-
```output
122
-
#Stream<[
123
-
enum: %File.Stream{
124
-
line_or_bytes: :line,
125
-
modes: [:raw, :read_ahead, :binary],
126
-
path: "day2.txt",
127
-
raw: true
128
-
},
129
-
funs: [#Function<47.58486609/1 in Stream.map/2>]
130
-
]>
131
-
```
132
-
133
-
### Task 1
134
-
135
-
```elixir
136
-
{h, d} =
137
-
stream
138
-
|> Enum.reduce({0, 0}, fn
139
-
{:forward, n}, {h, d} -> {h + n, d}
140
-
{:up, n}, {h, d} -> {h, d - n}
141
-
{:down, n}, {h, d} -> {h, d + n}
142
-
end)
143
-
144
-
h * d
145
-
```
146
-
147
-
```output
148
-
1499229
149
-
```
150
-
151
-
### Task 2
152
-
153
-
```elixir
154
-
{h, d, _} =
155
-
stream
156
-
|> Enum.reduce({0, 0, 0}, fn
157
-
{:forward, n}, {h, d, a} -> {h + n, d + a * n, a}
158
-
{:up, n}, {h, d, a} -> {h, d, a - n}
159
-
{:down, n}, {h, d, a} -> {h, d, a + n}
160
-
end)
161
-
162
-
h * d
163
-
```
164
-
165
-
```output
166
-
1340836560
167
-
```
168
-
169
-
## Day 3
170
-
171
-
### Input
172
-
173
-
```elixir
174
-
stream =
175
-
File.stream!("day3.txt")
176
-
|> Enum.map(&String.trim/1)
177
-
|> Enum.map(&String.to_charlist/1)
178
-
179
-
defmodule Day3 do
180
-
def count(list) do
181
-
Enum.reduce(list, List.duplicate(0, 12), fn input, acc ->
182
-
for {value, counter} <- Enum.zip(input, acc) do
183
-
case value do
184
-
?1 -> counter + 1
185
-
?0 -> counter
186
-
end
187
-
end
188
-
end)
189
-
end
190
-
end
191
-
```
192
-
193
-
```output
194
-
{:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}}
195
-
```
196
-
197
-
### Task 1
198
-
199
-
```elixir
200
-
half = div(length(stream), 2)
201
-
202
-
{a, b} =
203
-
stream
204
-
|> Day3.count()
205
-
|> Enum.reduce({0, 0}, fn elem, {a, b} ->
206
-
if elem > half do
207
-
{a * 2 + 1, b * 2}
208
-
else
209
-
{a * 2, b * 2 + 1}
210
-
end
211
-
end)
212
-
213
-
a * b
214
-
```
215
-
216
-
```output
217
-
3847100
218
-
```
219
-
220
-
### Task 2
221
-
222
-
```elixir
223
-
defmodule Day3.Task2 do
224
-
def reduce(list, cb), do: reduce(list, 0, cb)
225
-
226
-
defp reduce([elem], _, _), do: elem
227
-
228
-
defp reduce(list, at, cb) do
229
-
counts = Day3.count(list)
230
-
231
-
half = div(length(list), 2)
232
-
count = Enum.at(counts, at)
233
-
234
-
bit =
235
-
cond do
236
-
count == half and cb.(count + 1, half) -> ?1
237
-
count != half and cb.(count, half) -> ?1
238
-
true -> ?0
239
-
end
240
-
241
-
reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb)
242
-
end
243
-
end
244
-
245
-
co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2)
246
-
o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2)
247
-
248
-
co2 * o2
249
-
```
250
-
251
-
```output
252
-
4105235
253
-
```
254
-
255
-
## Day 4
256
-
257
-
### Input
258
-
259
-
This time it is a little bit more convoluted, as there are 2 parts of the input.
260
-
Fortunately we can easily disect the parts via pattern matching.
261
-
262
-
Technically the conversion to the numbers is not needed, but it does no harm
263
-
and provides additional layer of safety against some whitespace characters left there
264
-
and here.
265
-
266
-
The `Day4.win/2` function is manually unrolled, as it is easier to write than some
267
-
random jumping in the list.
268
-
269
-
<!-- livebook:{"disable_formatting":true} -->
270
-
271
-
```elixir
272
-
[numbers | bingos] =
273
-
File.read!("day4.txt")
274
-
|> String.split("\n\n", trim: true)
275
-
276
-
numbers =
277
-
numbers
278
-
|> String.trim()
279
-
|> String.split(",")
280
-
|> Enum.map(&String.to_integer/1)
281
-
282
-
bingos =
283
-
bingos
284
-
|> Enum.map(fn bingo ->
285
-
bingo
286
-
|> String.split(~r/\s+/, trim: true)
287
-
|> Enum.map(&String.to_integer/1)
288
-
end)
289
-
290
-
defmodule Day4 do
291
-
def win(
292
-
[
293
-
a1, a2, a3, a4, a5,
294
-
b1, b2, b3, b4, b5,
295
-
c1, c2, c3, c4, c5,
296
-
d1, d2, d3, d4, d5,
297
-
e1, e2, e3, e4, e5
298
-
],
299
-
nums
300
-
) do
301
-
# Rows
302
-
all_in([a1, a2, a3, a4, a5], nums) or
303
-
all_in([b1, b3, b3, b4, b5], nums) or
304
-
all_in([c1, c2, c3, c4, c5], nums) or
305
-
all_in([d1, d2, d3, d4, d5], nums) or
306
-
all_in([e1, e2, e3, e4, e5], nums) or
307
-
# Columns
308
-
all_in([a1, b1, c1, d1, e1], nums) or
309
-
all_in([a2, b2, c2, d2, e2], nums) or
310
-
all_in([a3, b3, c3, d3, e3], nums) or
311
-
all_in([a4, b4, c4, d4, e4], nums) or
312
-
all_in([a5, b5, c5, d5, e5], nums)
313
-
end
314
-
315
-
def not_matched(bingo, nums) do
316
-
Enum.reject(bingo, &(&1 in nums))
317
-
end
318
-
319
-
defp all_in(list, nums) do
320
-
Enum.all?(list, &(&1 in nums))
321
-
end
322
-
end
323
-
```
324
-
325
-
```output
326
-
{:module, Day4, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:all_in, 2}}
327
-
```
328
-
329
-
### Task 1
330
-
331
-
We simply traverse the `numbers` list aggregating the numbers (order doesn't really matter,
332
-
here we aggregate them in reverse order to speedup the code). When we have enough numbers
333
-
that any of the `bingos` is winning one, then we halt the reduction and return computed
334
-
result.
335
-
336
-
```elixir
337
-
numbers
338
-
|> Enum.reduce_while([], fn elem, acc ->
339
-
matches = [elem | acc]
340
-
341
-
case Enum.find(bingos, &Day4.win(&1, matches)) do
342
-
nil -> {:cont, matches}
343
-
bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
344
-
end
345
-
end)
346
-
```
347
-
348
-
```output
349
-
34506
350
-
```
351
-
352
-
### Task 2
353
-
354
-
```elixir
355
-
numbers
356
-
|> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} ->
357
-
matches = [elem | acc]
358
-
359
-
case bingos do
360
-
[bingo] ->
361
-
if Day4.win(bingo, matches) do
362
-
{:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
363
-
else
364
-
{:cont, {bingos, matches}}
365
-
end
366
-
367
-
_ ->
368
-
{:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}}
369
-
end
370
-
end)
371
-
```
372
-
373
-
```output
374
-
7686
375
-
```
376
-
377
-
## Day 5
378
-
379
-
```elixir
380
-
defmodule Day5 do
381
-
defmodule Point do
382
-
defstruct [:x, :y]
383
-
384
-
def parse(input) do
385
-
[x, y] = String.split(input, ",")
386
-
387
-
%__MODULE__{x: String.to_integer(x), y: String.to_integer(y)}
388
-
end
389
-
end
390
-
391
-
defmodule Line do
392
-
defstruct [:start, :finish]
393
-
394
-
def new(a, b) do
395
-
{start, finish} =
396
-
cond do
397
-
a.x < b.x -> {a, b}
398
-
a.y < b.y -> {a, b}
399
-
true -> {b, a}
400
-
end
401
-
402
-
%__MODULE__{start: start, finish: finish}
403
-
end
404
-
405
-
def horizontal?(a), do: a.start.y == a.finish.y
406
-
def vertical?(a), do: a.start.x == a.finish.x
407
-
408
-
def points(a) do
409
-
case {sign(a.finish.x - a.start.x), sign(a.finish.y - a.start.y)} do
410
-
{0, dy} -> for y <- a.start.y..a.finish.y//dy, do: {a.start.x, y}
411
-
{dx, 0} -> for x <- a.start.x..a.finish.x//dx, do: {x, a.start.y}
412
-
{dx, dy} -> Enum.zip(a.start.x..a.finish.x//dx, a.start.y..a.finish.y//dy)
413
-
end
414
-
end
415
-
416
-
def orientation(a) do
417
-
cond do
418
-
horizontal?(a) -> :horizontal
419
-
vertical?(a) -> :vertical
420
-
true -> :diagonal
421
-
end
422
-
end
423
-
424
-
defp sign(0), do: 0
425
-
defp sign(x) when x < 0, do: -1
426
-
defp sign(x) when x > 0, do: 1
427
-
end
428
-
end
429
-
430
-
lines =
431
-
File.stream!("day5.txt")
432
-
|> Stream.map(&String.trim/1)
433
-
|> Stream.map(fn input ->
434
-
[a, b] = String.split(input, " -> ")
435
-
436
-
pa = Day5.Point.parse(a)
437
-
pb = Day5.Point.parse(b)
438
-
439
-
Day5.Line.new(pa, pb)
440
-
end)
441
-
```
442
-
443
-
```output
444
-
#Stream<[
445
-
enum: %File.Stream{
446
-
line_or_bytes: :line,
447
-
modes: [:raw, :read_ahead, :binary],
448
-
path: "day5.txt",
449
-
raw: true
450
-
},
451
-
funs: [#Function<47.58486609/1 in Stream.map/2>, #Function<47.58486609/1 in Stream.map/2>]
452
-
]>
453
-
```
454
-
455
-
### Task 1
456
-
457
-
```elixir
458
-
lines
459
-
|> Stream.filter(&(Day5.Line.orientation(&1) != :diagonal))
460
-
|> Stream.flat_map(&Day5.Line.points/1)
461
-
|> Enum.frequencies()
462
-
|> Enum.count(fn {_k, v} -> v > 1 end)
463
-
```
464
-
465
-
```output
466
-
5197
467
-
```
468
-
469
-
### Task 2
470
-
471
-
```elixir
472
-
lines
473
-
|> Stream.flat_map(&Day5.Line.points/1)
474
-
|> Enum.frequencies()
475
-
|> Enum.count(fn {_k, v} -> v > 1 end)
476
-
```
477
-
478
-
```output
479
-
18605
480
-
```
481
-
482
-
## Day 6
483
-
484
-
```elixir
485
-
initial = for i <- 0..8, into: %{}, do: {i, 0}
486
-
487
-
counts =
488
-
File.read!("day6.txt")
489
-
|> String.trim()
490
-
|> String.split(",")
491
-
|> Enum.map(&String.to_integer/1)
492
-
|> Enum.frequencies()
493
-
|> Map.merge(initial, fn _, a, _ -> a end)
494
-
495
-
defmodule Day6 do
496
-
def next(%{0 => next} = population) do
497
-
1..8
498
-
|> Map.new(&{&1 - 1, population[&1]})
499
-
|> Map.merge(%{6 => next, 8 => next}, fn _, v1, v2 -> v1 + v2 end)
500
-
end
501
-
end
502
-
```
503
-
504
-
```output
505
-
{:module, Day6, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:next, 1}}
506
-
```
507
-
508
-
### Task 1
509
-
510
-
```elixir
511
-
1..80
512
-
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
513
-
|> Map.values()
514
-
|> Enum.sum()
515
-
```
516
-
517
-
```output
518
-
343441
519
-
```
520
-
521
-
### Task 2
522
-
523
-
```elixir
524
-
1..256
525
-
|> Enum.reduce(counts, fn _, acc -> Day6.next(acc) end)
526
-
|> Map.values()
527
-
|> Enum.sum()
528
-
```
529
-
530
-
```output
531
-
1569108373832
532
-
```
533
-
534
-
## Day 7
535
-
536
-
```elixir
537
-
input =
538
-
File.read!("day7.txt")
539
-
|> String.trim()
540
-
|> String.split(",")
541
-
|> Enum.map(&String.to_integer/1)
542
-
```
543
-
544
-
```output
545
-
[1101, 1, 29, 67, 1102, 0, 1, 65, 1008, 65, 35, 66, 1005, 66, 28, 1, 67, 65, 20, 4, 0, 1001, 65, 1,
546
-
65, 1106, 0, 8, 99, 35, 67, 101, 99, 105, 32, 110, 39, 101, 115, 116, 32, 112, 97, 115, 32, 117,
547
-
110, 101, 32, 105, ...]
548
-
```
549
-
550
-
### Task 1
551
-
552
-
```elixir
553
-
median = Enum.at(Enum.sort(input), div(length(input), 2))
554
-
555
-
input
556
-
|> Enum.map(&abs(&1 - median))
557
-
|> Enum.sum()
558
-
```
559
-
560
-
```output
561
-
336721
562
-
```
563
-
564
-
### Task 2
565
-
566
-
```elixir
567
-
arith_sum = fn n -> div(n * n + n, 2) end
568
-
569
-
max = Enum.max(input)
570
-
571
-
mean = Enum.sum(input) / length(input)
572
-
573
-
[floor(mean), ceil(mean)]
574
-
|> Enum.map(fn n ->
575
-
input
576
-
|> Enum.map(&arith_sum.(abs(&1 - n)))
577
-
|> Enum.sum()
578
-
end)
579
-
|> Enum.min()
580
-
```
581
-
582
-
```output
583
-
91638945
584
-
```
585
-
586
-
## Day 8
587
-
588
-
```elixir
589
-
input =
590
-
File.stream!("day8.txt")
591
-
|> Stream.map(fn line ->
592
-
line
593
-
|> String.split(" | ")
594
-
|> Enum.map(fn part ->
595
-
part
596
-
|> String.trim()
597
-
|> String.split(" ")
598
-
|> Enum.map(fn disp ->
599
-
# Sort characters in each entry to simplify later work
600
-
disp
601
-
|> String.to_charlist()
602
-
|> Enum.sort()
603
-
|> List.to_string()
604
-
end)
605
-
end)
606
-
|> List.to_tuple()
607
-
end)
608
-
```
609
-
610
-
```output
611
-
#Stream<[
612
-
enum: %File.Stream{
613
-
line_or_bytes: :line,
614
-
modes: [:raw, :read_ahead, :binary],
615
-
path: "day8.txt",
616
-
raw: true
617
-
},
618
-
funs: [#Function<47.58486609/1 in Stream.map/2>]
619
-
]>
620
-
```
621
-
622
-
### Task 1
623
-
624
-
We simply need to count all occurences of the values that have 2, 3, 4, or 7 highlighted
625
-
segments.
626
-
627
-
```elixir
628
-
input
629
-
|> Enum.map(fn {_, output} ->
630
-
Enum.count(output, &(byte_size(&1) in [2, 3, 4, 7]))
631
-
end)
632
-
|> Enum.sum()
633
-
```
634
-
635
-
```output
636
-
390
637
-
```
638
-
639
-
### Task 2
640
-
641
-
```elixir
642
-
defmodule Day8.Task2 do
643
-
defp a --- b, do: MapSet.difference(a, b)
644
-
645
-
defp a +++ b, do: MapSet.union(a, b)
646
-
647
-
defp a <~> b, do: MapSet.intersection(a, b)
648
-
649
-
# 1. 7. 4. 2|3|5. 2|3|5. 2|3|5. 6|9|0. 6|9|0. 6|9|0. 8.
650
-
def deduce([cf, acf, bcdf, acdeg, acdfg, abdfg, abdefg, abcdfg, abcefg, abcdefg]) do
651
-
eg = abcdefg --- (acf +++ bcdf)
652
-
bd = bcdf --- cf
653
-
adg = acdeg <~> acdfg <~> abdfg
654
-
abfg = abdefg <~> abcdfg <~> abcefg
655
-
a = acf --- cf
656
-
b = abfg <~> bd
657
-
f = abfg <~> cf
658
-
g = adg <~> eg
659
-
d = adg <~> bd
660
-
c = cf --- f
661
-
e = eg --- g
662
-
663
-
[a, b, c, d, e, f, g] =
664
-
[a, b, c, d, e, f, g]
665
-
|> Enum.map(&extract/1)
666
-
667
-
[
668
-
# 0
669
-
[a, b, c, e, f, g],
670
-
# 1
671
-
[c, f],
672
-
# 2
673
-
[a, c, d, e, g],
674
-
# 3
675
-
[a, c, d, f, g],
676
-
# 4
677
-
[b, c, d, f],
678
-
# 5
679
-
[a, b, d, f, g],
680
-
# 6
681
-
[a, b, d, e, f, g],
682
-
# 7
683
-
[a, c, f],
684
-
# 8
685
-
[a, b, c, d, e, f, g],
686
-
# 9
687
-
[a, b, c, d, f, g]
688
-
]
689
-
|> Enum.map(&List.to_string(Enum.sort(&1)))
690
-
|> Enum.with_index()
691
-
|> Map.new()
692
-
end
693
-
694
-
defp extract(a) do
695
-
# Just additional sanity check
696
-
[v] = MapSet.to_list(a)
697
-
698
-
v
699
-
end
700
-
701
-
def decode(matches, output) do
702
-
output
703
-
|> Enum.map(&matches[&1])
704
-
|> Integer.undigits()
705
-
end
706
-
end
707
-
708
-
input
709
-
|> Enum.map(fn {input, output} ->
710
-
input
711
-
|> Enum.sort_by(&byte_size/1)
712
-
|> Enum.map(&MapSet.new(String.to_charlist(&1)))
713
-
|> Day8.Task2.deduce()
714
-
|> Day8.Task2.decode(output)
715
-
end)
716
-
|> Enum.sum()
717
-
```
718
-
719
-
```output
720
-
1011785
721
-
```
722
-
723
-
## Day 9
724
-
725
-
```elixir
726
-
input =
727
-
File.read!("day9.txt")
728
-
|> String.split("\n", trim: true)
729
-
|> Enum.map(&String.to_charlist(String.trim(&1)))
730
-
|> Nx.tensor(names: [:y, :x])
731
-
|> Nx.subtract(?0)
732
-
|> Nx.add(1)
733
-
734
-
{width, height} = shape = Nx.shape(input)
735
-
```
736
-
737
-
```output
738
-
{100, 100}
739
-
```
740
-
741
-
### Task 1
742
-
743
-
```elixir
744
-
minima = fn padded, size, axis ->
745
-
shifted = Nx.slice_axis(padded, 0, size, axis)
746
-
x1 = Nx.less(input, shifted)
747
-
748
-
shifted = Nx.slice_axis(padded, 2, size, axis)
749
-
x2 = Nx.less(input, shifted)
750
-
751
-
Nx.logical_and(x1, x2)
752
-
end
753
-
754
-
padded = Nx.pad(input, 99, [{0, 0, 0}, {1, 1, 0}])
755
-
756
-
x = minima.(padded, width, :x)
757
-
758
-
padded = Nx.pad(input, 99, [{1, 1, 0}, {0, 0, 0}])
759
-
760
-
y = minima.(padded, height, :y)
761
-
762
-
minimas = Nx.logical_and(x, y)
763
-
764
-
input
765
-
|> Nx.multiply(minimas)
766
-
|> Nx.sum()
767
-
|> Nx.to_number()
768
-
```
769
-
770
-
```output
771
-
452
772
-
```
773
-
774
-
### Task 2
775
-
776
-
```elixir
777
-
input
778
-
|> Nx.equal(10)
779
-
|> Nx.logical_not()
780
-
|> Nx.select(Nx.iota(shape), 9999)
781
-
|> Nx.to_flat_list()
782
-
|> Enum.reject(&(&1 == 9999))
783
-
|> Enum.map(fn point -> {div(point, width), rem(point, width)} end)
784
-
|> Enum.reduce([], fn {y, x} = point, basins ->
785
-
basin_left = Enum.find_index(basins, &({y, x - 1} in &1))
786
-
basin_up = Enum.find_index(basins, &({y - 1, x} in &1))
787
-
788
-
case {basin_left, basin_up} do
789
-
{nil, nil} ->
790
-
[MapSet.new([point]) | basins]
791
-
792
-
{idx, nil} ->
793
-
List.update_at(basins, idx, &MapSet.put(&1, point))
794
-
795
-
{nil, idx} ->
796
-
List.update_at(basins, idx, &MapSet.put(&1, point))
797
-
798
-
{idx, idx} ->
799
-
List.update_at(basins, idx, &MapSet.put(&1, point))
800
-
801
-
{idx1, idx2} ->
802
-
{old, basins} = List.pop_at(basins, max(idx1, idx2))
803
-
804
-
List.update_at(basins, min(idx1, idx2), &(&1 |> MapSet.union(old) |> MapSet.put(point)))
805
-
end
806
-
end)
807
-
|> Enum.map(&MapSet.size/1)
808
-
|> Enum.sort(:desc)
809
-
|> Enum.take(3)
810
-
|> Enum.reduce(&*/2)
811
-
```
812
-
813
-
```output
814
-
1263735
815
-
```
816
-
817
-
## Day 10
818
-
819
-
```elixir
820
-
input =
821
-
File.stream!("day10.txt")
822
-
|> Stream.map(&String.trim/1)
823
-
824
-
defmodule Day10 do
825
-
@parens %{?( => ?), ?[ => ?], ?< => ?>, ?{ => ?}}
826
-
827
-
def parse(input), do: parse(input, [])
828
-
829
-
defp parse(<<c>> <> rest, stack) when c in '([{<', do: parse(rest, [@parens[c] | stack])
830
-
defp parse(<<c>> <> rest, [c | stack]), do: parse(rest, stack)
831
-
defp parse(<<>>, []), do: :ok
832
-
defp parse(<<>>, rest), do: {:incomplete, rest}
833
-
defp parse(<<c>> <> _, _), do: {:unexpected, [c]}
834
-
end
835
-
```
836
-
837
-
```output
838
-
{:module, Day10, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:parse, 2}}
839
-
```
840
-
841
-
### Task 1
842
-
843
-
```elixir
844
-
points = %{
845
-
?) => 3,
846
-
?] => 57,
847
-
?} => 1197,
848
-
?> => 25137
849
-
}
850
-
851
-
input
852
-
|> Enum.map(&Day10.parse/1)
853
-
|> Enum.map(fn
854
-
{:unexpected, [c]} -> points[c]
855
-
_ -> 0
856
-
end)
857
-
|> Enum.sum()
858
-
```
859
-
860
-
```output
861
-
288291
862
-
```
863
-
864
-
### Task 2
865
-
866
-
```elixir
867
-
points = %{
868
-
?) => 1,
869
-
?] => 2,
870
-
?} => 3,
871
-
?> => 4
872
-
}
873
-
874
-
median = fn list ->
875
-
sorted = Enum.sort(list)
876
-
middle = div(length(list), 2)
877
-
878
-
Enum.at(sorted, middle)
879
-
end
880
-
881
-
input
882
-
|> Enum.map(&Day10.parse/1)
883
-
|> Enum.flat_map(fn
884
-
{:incomplete, rest} ->
885
-
[
886
-
Enum.reduce(rest, 0, fn c, acc ->
887
-
acc * 5 + points[c]
888
-
end)
889
-
]
890
-
891
-
_ ->
892
-
[]
893
-
end)
894
-
|> median.()
895
-
```
896
-
897
-
```output
898
-
820045242
899
-
```
900
-
901
-
## Day 11
902
-
903
-
```elixir
904
-
input =
905
-
File.read!("day11.txt")
906
-
|> String.split("\n")
907
-
|> Enum.map(&String.trim/1)
908
-
|> Enum.map(fn line ->
909
-
for <<c <- line>>, do: c - ?0
910
-
end)
911
-
|> Enum.with_index()
912
-
|> Enum.flat_map(fn {row, y} ->
913
-
for {v, x} <- Enum.with_index(row), do: {{x, y}, v}
914
-
end)
915
-
|> Map.new()
916
-
917
-
defmodule Day11 do
918
-
def step(map) do
919
-
updated = Map.new(map, fn {k, v} -> {k, v + 1} end)
920
-
921
-
lightup(updated, 0)
922
-
end
923
-
924
-
@diffs for dx <- -1..1, dy <- -1..1, dx != 0 or dy != 0, do: {dx, dy}
925
-
926
-
def lightup(map, n) do
927
-
map
928
-
|> Enum.reduce({map, 0}, fn
929
-
{_, v}, acc when v < 10 ->
930
-
acc
931
-
932
-
{{x, y} = k, _}, {map, count} ->
933
-
new_map =
934
-
@diffs
935
-
|> Enum.reduce(map, fn {dx, dy}, acc ->
936
-
point = {x + dx, y + dy}
937
-
938
-
case Map.fetch(acc, point) do
939
-
{:ok, value} when value != 0 -> %{acc | point => value + 1}
940
-
_ -> acc
941
-
end
942
-
end)
943
-
|> Map.put(k, 0)
944
-
945
-
{new_map, count + 1}
946
-
end)
947
-
|> case do
948
-
{map, 0} -> {map, n}
949
-
{map, m} -> lightup(map, n + m)
950
-
end
951
-
end
952
-
end
953
-
```
954
-
955
-
```output
956
-
{:module, Day11, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:lightup, 2}}
957
-
```
958
-
959
-
### Task 1
960
-
961
-
```elixir
962
-
draw = fn map ->
963
-
for x <- 0..9 do
964
-
IO.puts(for y <- 0..9, do: ?0 + map[{x, y}])
965
-
end
966
-
967
-
IO.puts("")
968
-
end
969
-
970
-
1..100
971
-
|> Enum.reduce({input, 0}, fn _, {map, n} ->
972
-
{new_map, m} = Day11.step(map)
973
-
{new_map, n + m}
974
-
end)
975
-
|> elem(1)
976
-
```
977
-
978
-
```output
979
-
1688
980
-
```
981
-
982
-
### Task 2
983
-
984
-
```elixir
985
-
Stream.unfold(1, &{&1, &1 + 1})
986
-
|> Enum.reduce_while(input, fn idx, map ->
987
-
case Day11.step(map) do
988
-
{_, 100} -> {:halt, idx}
989
-
{next, _} -> {:cont, next}
990
-
end
991
-
end)
992
-
```
993
-
994
-
```output
995
-
403
996
-
```
997
-
998
-
## Day 12
999
-
1000
-
```elixir
1001
-
input =
1002
-
File.read!("day12.txt")
1003
-
|> String.split("\n")
1004
-
|> Enum.map(&String.split(&1, "-"))
1005
-
1006
-
graph =
1007
-
Enum.reduce(input, %{}, fn [a, b], acc ->
1008
-
acc
1009
-
|> Map.update(a, [b], &[b | &1])
1010
-
|> Map.update(b, [a], &[a | &1])
1011
-
end)
1012
-
1013
-
defmodule Day12 do
1014
-
def dfs(graph, start, finish), do: dfs(graph, start, finish, [start])
1015
-
1016
-
defp dfs(_graph, vertex, vertex, _visited), do: 1
1017
-
1018
-
defp dfs(graph, vertex, finish, visited) do
1019
-
(graph[vertex] -- visited)
1020
-
|> Enum.reduce(0, fn vertex, acc ->
1021
-
visited = if small?(vertex), do: [vertex | visited], else: visited
1022
-
1023
-
acc + dfs(graph, vertex, finish, visited)
1024
-
end)
1025
-
end
1026
-
1027
-
def dfs2(graph, start, finish), do: dfs2(graph, start, finish, %{start => :inf})
1028
-
1029
-
defp dfs2(_graph, vertex, vertex, _visited), do: 1
1030
-
1031
-
defp dfs2(graph, vertex, finish, visited) do
1032
-
(graph[vertex] -- keys(visited))
1033
-
|> Enum.reduce(0, fn vertex, acc ->
1034
-
visited = if small?(vertex), do: Map.update(visited, vertex, 1, &(&1 + 1)), else: visited
1035
-
1036
-
acc + dfs2(graph, vertex, finish, visited)
1037
-
end)
1038
-
end
1039
-
1040
-
defp keys(map) do
1041
-
if Enum.any?(map, fn {_, v} -> v == 2 end) do
1042
-
# there is already some vertex visited twice
1043
-
Map.keys(map)
1044
-
else
1045
-
for {k, v} <- map, v > 1, do: k
1046
-
end
1047
-
end
1048
-
1049
-
defp small?(<<c>> <> _), do: c in ?a..?z
1050
-
end
1051
-
```
1052
-
1053
-
```output
1054
-
{:module, Day12, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:small?, 1}}
1055
-
```
1056
-
1057
-
### Task 1
1058
-
1059
-
```elixir
1060
-
Day12.dfs(graph, "start", "end")
1061
-
```
1062
-
1063
-
```output
1064
-
4167
1065
-
```
1066
-
1067
-
### Task 2
1068
-
1069
-
```elixir
1070
-
Day12.dfs2(graph, "start", "end")
1071
-
```
1072
-
1073
-
```output
1074
-
98441
1075
-
```
1076
-
1077
-
## Day 13
1078
-
1079
-
```elixir
1080
-
[input, folds] =
1081
-
File.read!("day13.txt")
1082
-
|> String.trim()
1083
-
|> String.split("\n\n")
1084
-
1085
-
input =
1086
-
input
1087
-
|> String.split("\n")
1088
-
|> Enum.map(fn line ->
1089
-
[x, y] = String.split(line, ",")
1090
-
1091
-
{String.to_integer(x), String.to_integer(y)}
1092
-
end)
1093
-
|> MapSet.new()
1094
-
1095
-
folds =
1096
-
folds
1097
-
|> String.split("\n")
1098
-
|> Enum.map(fn
1099
-
"fold along " <> <<c>> <> "=" <> rest ->
1100
-
{String.to_atom(<<c>>), String.to_integer(rest)}
1101
-
end)
1102
-
1103
-
defmodule Day13 do
1104
-
def fold({orientation, pos}, set) do
1105
-
Enum.reduce(set, MapSet.new(), fn point, acc ->
1106
-
new_point = folded_coords(orientation, pos, point)
1107
-
1108
-
MapSet.put(acc, new_point)
1109
-
end)
1110
-
end
1111
-
1112
-
defp folded_coords(:x, col, {x, y}) when x > col, do: {abs(2 * col - x), y}
1113
-
defp folded_coords(:y, row, {x, y}) when y > row, do: {x, abs(2 * row - y)}
1114
-
defp folded_coords(_, _, point), do: point
1115
-
1116
-
def draw(set) do
1117
-
set
1118
-
|> Enum.group_by(&elem(&1, 1))
1119
-
|> Enum.sort()
1120
-
|> Enum.map(fn {_, points} ->
1121
-
points
1122
-
|> Enum.map(&elem(&1, 0))
1123
-
|> Enum.sort()
1124
-
|> Enum.chunk_every(2, 1)
1125
-
|> Enum.map(fn
1126
-
[a, b] -> b - a
1127
-
_ -> 0
1128
-
end)
1129
-
|> Enum.map(&String.pad_trailing("█", &1, " "))
1130
-
end)
1131
-
|> Enum.join("\n")
1132
-
end
1133
-
end
1134
-
```
1135
-
1136
-
```output
1137
-
{:module, Day13, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:draw, 1}}
1138
-
```
1139
-
1140
-
### Task 1
1141
-
1142
-
```elixir
1143
-
Day13.fold(hd(folds), input) |> MapSet.size()
1144
-
```
1145
-
1146
-
```output
1147
-
802
1148
-
```
1149
-
1150
-
### Task 2
1151
-
1152
-
```elixir
1153
-
Enum.reduce(folds, input, &Day13.fold/2)
1154
-
|> Day13.draw()
1155
-
|> IO.puts()
1156
-
```
1157
-
1158
-
```output
1159
-
███ █ █ █ █ ████ ████ ██ █ █ ███
1160
-
█ █ █ █ █ █ █ █ █ █ █ █ █ █
1161
-
█ █ ██ ████ ███ █ █ █ █ ███
1162
-
███ █ █ █ █ █ █ █ ██ █ █ █ █
1163
-
█ █ █ █ █ █ █ █ █ █ █ █ █ █
1164
-
█ █ █ █ █ █ █ ████ ███ ██ ███
1165
-
```
1166
-
1167
-
```output
1168
-
:ok
1169
-
```
1170
-
1171
-
## Day 14
1172
-
1173
-
```elixir
1174
-
[polymer_raw, subs] =
1175
-
File.read!("day14.txt")
1176
-
|> String.split("\n\n")
1177
-
1178
-
<<first, _::binary>> = polymer_raw
1179
-
1180
-
polymer =
1181
-
{first,
1182
-
polymer_raw
1183
-
|> String.to_charlist()
1184
-
|> Enum.chunk_every(2, 1, :discard)
1185
-
|> Enum.frequencies()}
1186
-
1187
-
subs =
1188
-
subs
1189
-
|> String.trim()
1190
-
|> String.split(["\n", " -> "])
1191
-
|> Enum.chunk_every(2)
1192
-
|> Map.new(fn [pair, <<new>>] -> {String.to_charlist(pair), new} end)
1193
-
1194
-
defmodule Day14 do
1195
-
def expand({hd, polymer}, subs) do
1196
-
new =
1197
-
polymer
1198
-
|> Enum.reduce(%{}, fn {[a, b] = pair, count}, acc ->
1199
-
s = Map.fetch!(subs, pair)
1200
-
1201
-
acc
1202
-
|> Map.update([a, s], count, &(&1 + count))
1203
-
|> Map.update([s, b], count, &(&1 + count))
1204
-
end)
1205
-
1206
-
{hd, new}
1207
-
end
1208
-
1209
-
def expand_naive(polymer, subs) do
1210
-
polymer
1211
-
|> to_charlist()
1212
-
|> Enum.chunk_every(2, 1, :discard)
1213
-
|> Enum.flat_map(fn [a, b] = pair ->
1214
-
[a, subs[pair], b]
1215
-
end)
1216
-
|> List.to_string()
1217
-
end
1218
-
1219
-
def frequencies({hd, polymer}) do
1220
-
polymer
1221
-
|> Enum.reduce(%{hd => 1}, fn {[_, b], count}, acc ->
1222
-
Map.update(acc, b, count, &(&1 + count))
1223
-
end)
1224
-
end
1225
-
end
1226
-
```
1227
-
1228
-
```output
1229
-
{:module, Day14, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:frequencies, 1}}
1230
-
```
1231
-
1232
-
### Task 1
1233
-
1234
-
```elixir
1235
-
{{_, min}, {_, max}} =
1236
-
1..10
1237
-
|> Enum.reduce(polymer, fn _, acc ->
1238
-
Day14.expand(acc, subs)
1239
-
end)
1240
-
|> Day14.frequencies()
1241
-
|> Enum.min_max_by(&elem(&1, 1))
1242
-
1243
-
# 2768
1244
-
max - min
1245
-
```
1246
-
1247
-
```output
1248
-
2768
1249
-
```
1250
-
1251
-
### Task 2
1252
-
1253
-
```elixir
1254
-
{{_, min}, {_, max}} =
1255
-
1..40
1256
-
|> Enum.reduce(polymer, fn _, acc ->
1257
-
Day14.expand(acc, subs)
1258
-
end)
1259
-
|> Day14.frequencies()
1260
-
|> Enum.min_max_by(&elem(&1, 1))
1261
-
1262
-
max - min
1263
-
```
1264
-
1265
-
```output
1266
-
2914365137499
1267
-
```
1268
-
1269
-
## Day 15
1270
-
1271
-
```elixir
1272
-
input =
1273
-
File.read!("day15.txt")
1274
-
|> String.trim()
1275
-
|> String.split("\n")
1276
-
|> Enum.map(&String.to_charlist/1)
1277
-
|> Enum.with_index()
1278
-
|> Enum.flat_map(fn {row, y} ->
1279
-
row
1280
-
|> Enum.with_index()
1281
-
|> Enum.map(fn {v, x} -> {{x, y}, v - ?0} end)
1282
-
end)
1283
-
|> Map.new()
1284
-
1285
-
{width, height} = Enum.max(Map.keys(input))
1286
-
```
1287
-
1288
-
```output
1289
-
{99, 99}
1290
-
```
1291
-
1292
-
### Task 1
1293
-
1294
-
```elixir
1295
-
shortest_paths =
1296
-
for y <- height..0//-1,
1297
-
x <- width..0//-1,
1298
-
reduce: %{} do
1299
-
acc ->
1300
-
right = acc[{x + 1, y}]
1301
-
bottom = acc[{x, y + 1}]
1302
-
1303
-
value =
1304
-
case {right, bottom} do
1305
-
{nil, nil} -> input[{x, y}]
1306
-
_ -> input[{x, y}] + min(right, bottom)
1307
-
end
1308
-
1309
-
Map.put(acc, {x, y}, value)
1310
-
end
1311
-
1312
-
shortest_paths[{0, 0}] - input[{0, 0}]
1313
-
```
1314
-
1315
-
```output
1316
-
429
1317
-
```
1318
-
1319
-
### Task 2
1320
-
1321
-
```elixir
1322
-
defmodule Day15.Task2 do
1323
-
def expand_grid(board) do
1324
-
{width, height} = Enum.max(Map.keys(board))
1325
-
1326
-
board
1327
-
|> Enum.flat_map(fn {{x, y}, v} ->
1328
-
for rx <- 0..4, ry <- 0..4 do
1329
-
{{x + (width + 1) * rx, y + (height + 1) * ry}, rem(v - 1 + rx + ry, 9) + 1}
1330
-
end
1331
-
end)
1332
-
|> Map.new()
1333
-
end
1334
-
1335
-
def find_path(board, start, finish) do
1336
-
dists = :gb_sets.singleton({0, start})
1337
-
1338
-
find_path(board, finish, dists, MapSet.new())
1339
-
end
1340
-
1341
-
@surround for dx <- -1..1, dy <- -1..1, abs(dx) != abs(dy), do: {dx, dy}
1342
-
1343
-
def find_path(board, finish, dists, visited) do
1344
-
{{dist, {x, y} = curr}, dists} = :gb_sets.take_smallest(dists)
1345
-
1346
-
if curr == finish do
1347
-
dist
1348
-
else
1349
-
visited = MapSet.put(visited, curr)
1350
-
1351
-
dists =
1352
-
for {dx, dy} <- @surround,
1353
-
next = {x + dx, y + dy},
1354
-
next not in visited,
1355
-
is_map_key(board, next),
1356
-
alt = dist + board[next],
1357
-
reduce: dists do
1358
-
acc ->
1359
-
:gb_sets.add_element({alt, next}, acc)
1360
-
end
1361
-
1362
-
find_path(board, finish, dists, visited)
1363
-
end
1364
-
end
1365
-
end
1366
-
```
1367
-
1368
-
```output
1369
-
{:module, Day15.Task2, <<70, 79, 82, 49, 0, 0, 16, ...>>, {:find_path, 4}}
1370
-
```
1371
-
1372
-
```elixir
1373
-
input
1374
-
|> Day15.Task2.expand_grid()
1375
-
|> Day15.Task2.find_path({0, 0}, {499, 499})
1376
-
```
1377
-
1378
-
```output
1379
-
2844
1380
-
```
1381
-
1382
-
## Day 16
1383
-
1384
-
```elixir
1385
-
defmodule Day16 do
1386
-
defmodule Packet do
1387
-
defstruct [:version, :type, :value]
1388
-
end
1389
-
1390
-
def decode(<<version::3, 4::3, rest::bitstring>>) do
1391
-
{value, rest} = literal(rest, 0)
1392
-
1393
-
{%Packet{type: 4, version: version, value: value}, rest}
1394
-
end
1395
-
1396
-
def decode(<<version::3, type::3, 0::1, length::15, rest::bitstring>>) do
1397
-
<<subpackets::bitstring-size(length), rest::bitstring>> = rest
1398
-
1399
-
{%Packet{type: type, version: version, value: decode_all(subpackets)}, rest}
1400
-
end
1401
-
1402
-
def decode(<<version::3, type::3, 1::1, length::11, rest::bitstring>>) do
1403
-
{value, rest} = Enum.map_reduce(1..length, rest, fn _, acc -> decode(acc) end)
1404
-
1405
-
{%Packet{type: type, version: version, value: value}, rest}
1406
-
end
1407
-
1408
-
def decode_all(input) do
1409
-
case decode(input) do
1410
-
{packet, <<>>} -> [packet]
1411
-
{packet, rest} -> [packet | decode_all(rest)]
1412
-
end
1413
-
end
1414
-
1415
-
defp literal(<<1::1, bits::4, rest::bitstring>>, acc) do
1416
-
literal(rest, acc * 0x10 + bits)
1417
-
end
1418
-
1419
-
defp literal(<<0::1, bits::4, rest::bitstring>>, acc) do
1420
-
{acc * 0x10 + bits, rest}
1421
-
end
1422
-
end
1423
-
1424
-
input =
1425
-
File.read!("day16.txt")
1426
-
|> String.trim()
1427
-
|> Base.decode16!()
1428
-
|> Day16.decode()
1429
-
|> elem(0)
1430
-
```
1431
-
1432
-
```output
1433
-
%Day16.Packet{
1434
-
type: 0,
1435
-
value: [
1436
-
%Day16.Packet{
1437
-
type: 1,
1438
-
value: [
1439
-
%Day16.Packet{type: 4, value: 20, version: 6},
1440
-
%Day16.Packet{
1441
-
type: 6,
1442
-
value: [
1443
-
%Day16.Packet{type: 4, value: 14747, version: 1},
1444
-
%Day16.Packet{type: 4, value: 14747, version: 6}
1445
-
],
1446
-
version: 2
1447
-
}
1448
-
],
1449
-
version: 1
1450
-
},
1451
-
%Day16.Packet{
1452
-
type: 3,
1453
-
value: [
1454
-
%Day16.Packet{type: 4, value: 15, version: 5},
1455
-
%Day16.Packet{type: 4, value: 10, version: 6}
1456
-
],
1457
-
version: 7
1458
-
},
1459
-
%Day16.Packet{
1460
-
type: 1,
1461
-
value: [
1462
-
%Day16.Packet{
1463
-
type: 7,
1464
-
value: [
1465
-
%Day16.Packet{type: 4, value: 2184, version: 1},
1466
-
%Day16.Packet{type: 4, value: 130250, version: 6}
1467
-
],
1468
-
version: 6
1469
-
},
1470
-
%Day16.Packet{type: 4, value: 5442981, version: 4}
1471
-
],
1472
-
version: 6
1473
-
},
1474
-
%Day16.Packet{type: 4, value: 8281083, version: 0},
1475
-
%Day16.Packet{
1476
-
type: 2,
1477
-
value: [
1478
-
%Day16.Packet{type: 4, value: 102, version: 5},
1479
-
%Day16.Packet{type: 4, value: 647125, version: 7}
1480
-
],
1481
-
version: 1
1482
-
},
1483
-
%Day16.Packet{
1484
-
type: 1,
1485
-
value: [
1486
-
%Day16.Packet{type: 4, value: 178, version: 1},
1487
-
%Day16.Packet{type: 4, value: 176, version: 6}
1488
-
],
1489
-
version: 0
1490
-
},
1491
-
%Day16.Packet{
1492
-
type: 1,
1493
-
value: [
1494
-
%Day16.Packet{
1495
-
type: 6,
1496
-
value: [
1497
-
%Day16.Packet{
1498
-
type: 0,
1499
-
value: [
1500
-
%Day16.Packet{type: 4, value: 13, version: 1},
1501
-
%Day16.Packet{type: 4, value: 8, version: 4},
1502
-
%Day16.Packet{type: 4, value: 4, version: 3}
1503
-
],
1504
-
version: 2
1505
-
},
1506
-
%Day16.Packet{
1507
-
type: 0,
1508
-
value: [
1509
-
%Day16.Packet{type: 4, value: 7, version: 7},
1510
-
%Day16.Packet{type: 4, value: 11, version: 3},
1511
-
%Day16.Packet{type: 4, value: 14, version: 2}
1512
-
],
1513
-
version: 4
1514
-
}
1515
-
],
1516
-
version: 7
1517
-
},
1518
-
%Day16.Packet{type: 4, value: 2724, version: 0}
1519
-
],
1520
-
version: 1
1521
-
},
1522
-
%Day16.Packet{type: 4, value: 9, version: 4},
1523
-
%Day16.Packet{
1524
-
type: 1,
1525
-
value: [
1526
-
%Day16.Packet{
1527
-
type: 5,
1528
-
value: [
1529
-
%Day16.Packet{type: 4, value: 7240238, version: 2},
1530
-
%Day16.Packet{type: 4, value: 233, version: 7}
1531
-
],
1532
-
version: 1
1533
-
},
1534
-
%Day16.Packet{type: 4, value: 37, version: 6}
1535
-
],
1536
-
version: 4
1537
-
},
1538
-
%Day16.Packet{type: 2, value: [%Day16.Packet{type: 4, value: 2, version: 5}], version: 5},
1539
-
%Day16.Packet{type: 4, value: 53749, version: 4},
1540
-
%Day16.Packet{type: 4, value: 11, version: 3},
1541
-
%Day16.Packet{
1542
-
type: 1,
1543
-
value: [
1544
-
%Day16.Packet{type: 4, value: 382979, version: 4},
1545
-
%Day16.Packet{
1546
-
type: 5,
1547
-
value: [
1548
-
%Day16.Packet{
1549
-
type: 0,
1550
-
value: [
1551
-
%Day16.Packet{type: 4, value: 15, version: 1},
1552
-
%Day16.Packet{type: 4, value: 10, version: 0},
1553
-
%Day16.Packet{type: 4, value: 2, version: 6}
1554
-
],
1555
-
version: 5
1556
-
},
1557
-
%Day16.Packet{
1558
-
type: 0,
1559
-
value: [
1560
-
%Day16.Packet{type: 4, value: 4, version: 7},
1561
-
%Day16.Packet{type: 4, value: 7, version: 4},
1562
-
%Day16.Packet{type: 4, value: 2, version: 5}
1563
-
],
1564
-
version: 1
1565
-
}
1566
-
],
1567
-
version: 6
1568
-
}
1569
-
],
1570
-
version: 2
1571
-
},
1572
-
%Day16.Packet{type: 4, value: 21251, version: 1},
1573
-
%Day16.Packet{
1574
-
type: 1,
1575
-
value: [
1576
-
%Day16.Packet{type: 4, value: 163, version: 6},
1577
-
%Day16.Packet{
1578
-
type: 5,
1579
-
value: [
1580
-
%Day16.Packet{type: 4, value: 59, version: 3},
1581
-
%Day16.Packet{type: 4, value: 836848134220, version: 1}
1582
-
],
1583
-
version: 6
1584
-
}
1585
-
],
1586
-
version: 2
1587
-
},
1588
-
%Day16.Packet{
1589
-
type: 2,
1590
-
value: [
1591
-
%Day16.Packet{
1592
-
type: 0,
1593
-
value: [
1594
-
%Day16.Packet{
1595
-
type: 0,
1596
-
value: [
1597
-
%Day16.Packet{
1598
-
type: 2,
1599
-
value: [
1600
-
%Day16.Packet{
1601
-
type: 2,
1602
-
value: [
1603
-
%Day16.Packet{
1604
-
type: 0,
1605
-
value: [
1606
-
%Day16.Packet{
1607
-
type: 3,
1608
-
value: [
1609
-
%Day16.Packet{
1610
-
type: 2,
1611
-
value: [
1612
-
%Day16.Packet{
1613
-
type: 2,
1614
-
value: [
1615
-
%Day16.Packet{
1616
-
type: 3,
1617
-
value: [%Day16.Packet{type: 0, value: [...], ...}],
1618
-
version: 0
1619
-
}
1620
-
],
1621
-
version: 1
1622
-
}
1623
-
],
1624
-
version: 1
1625
-
}
1626
-
],
1627
-
version: 7
1628
-
}
1629
-
],
1630
-
version: 0
1631
-
}
1632
-
],
1633
-
version: 6
1634
-
}
1635
-
],
1636
-
version: 2
1637
-
}
1638
-
],
1639
-
version: 2
1640
-
}
1641
-
],
1642
-
version: 6
1643
-
}
1644
-
],
1645
-
version: 7
1646
-
},
1647
-
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 4, value: 44, version: 4}], version: 7},
1648
-
%Day16.Packet{
1649
-
type: 1,
1650
-
value: [
1651
-
%Day16.Packet{type: 4, value: 255, version: 2},
1652
-
%Day16.Packet{type: 4, value: 91, version: 5},
1653
-
%Day16.Packet{type: 4, value: 176, version: 5},
1654
-
%Day16.Packet{type: 4, value: 23, version: 1}
1655
-
],
1656
-
version: 7
1657
-
},
1658
-
%Day16.Packet{
1659
-
type: 3,
1660
-
value: [
1661
-
%Day16.Packet{type: 4, value: 11520, version: 4},
1662
-
%Day16.Packet{type: 4, value: 6069, version: 0},
1663
-
%Day16.Packet{type: 4, value: 1089149511401, version: 4},
1664
-
%Day16.Packet{type: 4, value: 158, version: 2},
1665
-
%Day16.Packet{type: 4, value: 620605, version: 0}
1666
-
],
1667
-
version: 2
1668
-
},
1669
-
%Day16.Packet{
1670
-
type: 0,
1671
-
value: [
1672
-
%Day16.Packet{type: 4, value: 62788, version: 7},
1673
-
%Day16.Packet{type: 4, value: 9410622, version: 2},
1674
-
%Day16.Packet{type: 4, value: 15912821, version: 4}
1675
-
],
1676
-
version: 4
1677
-
},
1678
-
%Day16.Packet{
1679
-
type: 1,
1680
-
value: [
1681
-
%Day16.Packet{type: 4, value: 22416, version: 5},
1682
-
%Day16.Packet{
1683
-
type: 5,
1684
-
value: [
1685
-
%Day16.Packet{type: 4, value: 246, version: 1},
1686
-
%Day16.Packet{type: 4, value: 246, version: 4}
1687
-
],
1688
-
version: 2
1689
-
}
1690
-
],
1691
-
version: 0
1692
-
},
1693
-
%Day16.Packet{type: 3, value: [%Day16.Packet{type: 4, value: 13008601, version: 5}], version: 0},
1694
-
%Day16.Packet{
1695
-
type: 0,
1696
-
value: [
1697
-
%Day16.Packet{
1698
-
type: 1,
1699
-
value: [
1700
-
%Day16.Packet{type: 4, value: 3, version: 4},
1701
-
%Day16.Packet{type: 4, value: 14, version: 1},
1702
-
%Day16.Packet{type: 4, value: 5, version: 0}
1703
-
],
1704
-
version: 5
1705
-
},
1706
-
%Day16.Packet{
1707
-
type: 1,
1708
-
value: [
1709
-
%Day16.Packet{type: 4, value: 2, version: 1},
1710
-
%Day16.Packet{type: 4, value: 14, version: 1},
1711
-
%Day16.Packet{type: 4, value: 10, version: 1}
1712
-
],
1713
-
version: 6
1714
-
},
1715
-
%Day16.Packet{
1716
-
type: 1,
1717
-
value: [
1718
-
%Day16.Packet{type: 4, value: 8, version: 3},
1719
-
%Day16.Packet{type: 4, value: 6, version: 6},
1720
-
%Day16.Packet{type: 4, value: 11, version: 0}
1721
-
],
1722
-
version: 1
1723
-
}
1724
-
],
1725
-
version: 5
1726
-
},
1727
-
%Day16.Packet{
1728
-
type: 1,
1729
-
value: [
1730
-
%Day16.Packet{type: 4, value: 32940592237, version: 2},
1731
-
%Day16.Packet{
1732
-
type: 5,
1733
-
value: [
1734
-
%Day16.Packet{type: 4, value: 100, version: 1},
1735
-
%Day16.Packet{type: 4, value: 1393232728, version: 2}
1736
-
],
1737
-
version: 2
1738
-
}
1739
-
],
1740
-
version: 0
1741
-
},
1742
-
%Day16.Packet{type: 4, value: 89, version: 3},
1743
-
%Day16.Packet{
1744
-
type: 2,
1745
-
value: [
1746
-
%Day16.Packet{type: 4, value: 204, version: 6},
1747
-
%Day16.Packet{type: 4, value: 260321821, version: 2},
1748
-
%Day16.Packet{type: 4, value: 225241983, version: 6}
1749
-
],
1750
-
version: 0
1751
-
},
1752
-
%Day16.Packet{
1753
-
type: 0,
1754
-
value: [
1755
-
%Day16.Packet{type: 4, value: 960899, version: 3},
1756
-
%Day16.Packet{type: 4, value: 58997, version: 5},
1757
-
%Day16.Packet{type: 4, value: 54940, version: 6},
1758
-
%Day16.Packet{type: 4, value: 10974, version: 2},
1759
-
%Day16.Packet{type: 4, value: 882043, version: 2}
1760
-
],
1761
-
version: 0
1762
-
},
1763
-
%Day16.Packet{
1764
-
type: 1,
1765
-
value: [
1766
-
%Day16.Packet{
1767
-
type: 6,
1768
-
value: [
1769
-
%Day16.Packet{type: 4, value: 35633017255, version: 4},
1770
-
%Day16.Packet{type: 4, value: 35633017255, version: 2}
1771
-
],
1772
-
version: 3
1773
-
},
1774
-
%Day16.Packet{type: 4, value: 1359, version: 6}
1775
-
],
1776
-
version: 6
1777
-
},
1778
-
%Day16.Packet{
1779
-
type: 1,
1780
-
value: [
1781
-
%Day16.Packet{type: 4, value: 92, version: 4},
1782
-
%Day16.Packet{type: 4, value: 38, version: 3},
1783
-
%Day16.Packet{type: 4, value: 160, version: 5},
1784
-
%Day16.Packet{type: 4, value: 111, version: 1},
1785
-
%Day16.Packet{type: 4, value: 64, version: 4}
1786
-
],
1787
-
version: 4
1788
-
},
1789
-
%Day16.Packet{
1790
-
type: 0,
1791
-
value: [
1792
-
%Day16.Packet{type: 4, value: 2541, version: 3},
1793
-
%Day16.Packet{type: 4, value: 263947, version: 6},
1794
-
%Day16.Packet{type: 4, value: 7686705, version: 5},
1795
-
%Day16.Packet{type: 4, value: 31, version: 4}
1796
-
],
1797
-
version: 2
1798
-
},
1799
-
%Day16.Packet{
1800
-
type: 1,
1801
-
value: [
1802
-
%Day16.Packet{
1803
-
type: 6,
1804
-
value: [
1805
-
%Day16.Packet{type: 4, value: 3193865, version: 1},
1806
-
%Day16.Packet{type: 4, value: 20223, version: 7}
1807
-
],
1808
-
version: 2
1809
-
},
1810
-
%Day16.Packet{type: 4, value: 9328522, version: 5}
1811
-
],
1812
-
version: 0
1813
-
},
1814
-
%Day16.Packet{
1815
-
type: 2,
1816
-
value: [
1817
-
%Day16.Packet{type: 4, value: 5, version: 4},
1818
-
%Day16.Packet{type: 4, value: 7, version: 3},
1819
-
%Day16.Packet{type: 4, value: 179420284, version: 4},
1820
-
%Day16.Packet{type: 4, value: 19890, version: 1},
1821
-
%Day16.Packet{type: 4, value: 2655, version: 0}
1822
-
],
1823
-
version: 7
1824
-
},
1825
-
%Day16.Packet{
1826
-
type: 1,
1827
-
value: [
1828
-
%Day16.Packet{type: 4, value: 862089, version: 1},
1829
-
%Day16.Packet{
1830
-
type: 6,
1831
-
value: [
1832
-
%Day16.Packet{type: 4, value: 248, version: 3},
1833
-
%Day16.Packet{type: 4, value: 3286, version: 5}
1834
-
],
1835
-
version: 3
1836
-
}
1837
-
],
1838
-
version: 3
1839
-
},
1840
-
%Day16.Packet{
1841
-
type: 1,
1842
-
value: [
1843
-
%Day16.Packet{type: 4, value: 93, version: 6},
1844
-
%Day16.Packet{
1845
-
type: 5,
1846
-
value: [
1847
-
%Day16.Packet{type: 4, value: 4269, version: 6},
1848
-
%Day16.Packet{type: 4, value: 240, version: 3}
1849
-
],
1850
-
version: 4
1851
-
}
1852
-
],
1853
-
version: 5
1854
-
},
1855
-
%Day16.Packet{
1856
-
type: 3,
1857
-
value: [
1858
-
%Day16.Packet{type: 4, value: 2938, version: 6},
1859
-
%Day16.Packet{type: 4, value: 3, version: 6},
1860
-
%Day16.Packet{type: 4, value: 211, version: 7}
1861
-
],
1862
-
version: 3
1863
-
},
1864
-
%Day16.Packet{
1865
-
type: 1,
1866
-
value: [
1867
-
%Day16.Packet{
1868
-
type: 7,
1869
-
value: [
1870
-
%Day16.Packet{type: 4, value: 159, version: 0},
1871
-
%Day16.Packet{type: 4, value: 159, version: 5}
1872
-
],
1873
-
version: 0
1874
-
},
1875
-
%Day16.Packet{type: 4, value: 28, version: 1}
1876
-
],
1877
-
version: 4
1878
-
},
1879
-
%Day16.Packet{type: 4, value: 84, version: 4},
1880
-
%Day16.Packet{
1881
-
type: 1,
1882
-
value: [
1883
-
%Day16.Packet{type: 4, value: 235, version: 4},
1884
-
%Day16.Packet{
1885
-
type: 6,
1886
-
value: [
1887
-
%Day16.Packet{type: 0, value: [%Day16.Packet{...}, ...], version: 4},
1888
-
%Day16.Packet{type: 0, value: [...], ...}
1889
-
],
1890
-
version: 3
1891
-
}
1892
-
],
1893
-
version: 6
1894
-
},
1895
-
%Day16.Packet{type: 4, value: 1425, version: 4},
1896
-
%Day16.Packet{
1897
-
type: 1,
1898
-
value: [
1899
-
%Day16.Packet{
1900
-
type: 7,
1901
-
value: [%Day16.Packet{type: 0, value: [...], ...}, %Day16.Packet{type: 0, ...}],
1902
-
version: 5
1903
-
},
1904
-
%Day16.Packet{type: 4, value: 13, version: 2}
1905
-
],
1906
-
version: 2
1907
-
},
1908
-
%Day16.Packet{type: 0, value: [%Day16.Packet{type: 4, value: 3121, version: 6}], version: 5},
1909
-
%Day16.Packet{
1910
-
type: 1,
1911
-
value: [
1912
-
%Day16.Packet{type: 4, value: 51, version: 2},
1913
-
%Day16.Packet{type: 4, value: 61, ...},
1914
-
%Day16.Packet{type: 4, ...}
1915
-
],
1916
-
version: 4
1917
-
},
1918
-
%Day16.Packet{
1919
-
type: 1,
1920
-
value: [%Day16.Packet{type: 4, value: 1393, ...}, %Day16.Packet{type: 5, ...}],
1921
-
version: 3
1922
-
},
1923
-
%Day16.Packet{type: 1, value: [%Day16.Packet{type: 7, ...}, %Day16.Packet{...}], version: 3},
1924
-
%Day16.Packet{type: 1, value: [%Day16.Packet{...}, ...], version: 7},
1925
-
%Day16.Packet{type: 3, value: [...], ...},
1926
-
%Day16.Packet{type: 2, ...},
1927
-
%Day16.Packet{...},
1928
-
...
1929
-
],
1930
-
version: 3
1931
-
}
1932
-
```
1933
-
1934
-
### Task 1
1935
-
1936
-
```elixir
1937
-
defmodule Day16.Task1 do
1938
-
alias Day16.Packet
1939
-
1940
-
def sum(%Packet{type: 4, version: version}), do: version
1941
-
1942
-
def sum(%Packet{version: version, value: value}) do
1943
-
Enum.reduce(value, version, &(sum(&1) + &2))
1944
-
end
1945
-
end
1946
-
1947
-
Day16.Task1.sum(input)
1948
-
```
1949
-
1950
-
```output
1951
-
949
1952
-
```
1953
-
1954
-
### Task 2
1955
-
1956
-
```elixir
1957
-
defmodule Day16.Task2 do
1958
-
alias Day16.Packet
1959
-
1960
-
def evaluate(%Packet{type: 0} = packet), do: reduce(packet, 0, &+/2)
1961
-
def evaluate(%Packet{type: 1} = packet), do: reduce(packet, 1, &*/2)
1962
-
def evaluate(%Packet{type: 2} = packet), do: reduce(packet, :inf, &min/2)
1963
-
def evaluate(%Packet{type: 3} = packet), do: reduce(packet, 0, &max/2)
1964
-
1965
-
def evaluate(%Packet{type: 4, value: value}), do: value
1966
-
1967
-
def evaluate(%Packet{type: 5} = packet), do: compare(packet, &>/2)
1968
-
def evaluate(%Packet{type: 6} = packet), do: compare(packet, &</2)
1969
-
def evaluate(%Packet{type: 7} = packet), do: compare(packet, &==/2)
1970
-
1971
-
defp reduce(%Packet{value: value}, initial, op) do
1972
-
Enum.reduce(value, initial, &op.(evaluate(&1), &2))
1973
-
end
1974
-
1975
-
defp compare(%Packet{value: [a, b]}, op) do
1976
-
if op.(evaluate(a), evaluate(b)), do: 1, else: 0
1977
-
end
1978
-
end
1979
-
1980
-
Day16.Task2.evaluate(input)
1981
-
```
1982
-
1983
-
```output
1984
-
1114600142730
1985
-
```