tangled
alpha
login
or
join now
hauleth.dev
/
advent-of-code
3
fork
atom
this repo has no description
3
fork
atom
overview
issues
pulls
pipelines
Day 08 of 2025
hauleth.dev
3 months ago
90dd84ae
8ceaee32
verified
This commit was signed with the committer's
known signature
.
hauleth.dev
SSH Key Fingerprint:
SHA256:1hEP8QO8nM2KQfQ8jK4Q19y/CmqVZQI/cNSht3c1QlI=
+116
1 changed file
expand all
collapse all
unified
split
2025
day08.livemd
+116
2025/day08.livemd
···
1
1
+
# Day 08
2
2
+
3
3
+
```elixir
4
4
+
Mix.install([:kino_aoc])
5
5
+
```
6
6
+
7
7
+
## Parse
8
8
+
9
9
+
<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiI4Iiwic2Vzc2lvbl9zZWNyZXQiOiJBRFZFTlRfT0ZfQ09ERV9TRVNTSU9OIiwieWVhciI6IjIwMjUifQ","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
10
10
+
11
11
+
```elixir
12
12
+
{:ok, puzzle_input} =
13
13
+
KinoAOC.download_puzzle("2025", "8", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
14
14
+
```
15
15
+
16
16
+
```elixir
17
17
+
boxes =
18
18
+
puzzle_input
19
19
+
|> String.split()
20
20
+
|> Enum.map(fn raw ->
21
21
+
raw
22
22
+
|> String.split(",")
23
23
+
|> Enum.map(&String.to_integer/1)
24
24
+
|> List.to_tuple()
25
25
+
end)
26
26
+
|> Enum.sort()
27
27
+
```
28
28
+
29
29
+
## Setup
30
30
+
31
31
+
```elixir
32
32
+
defmodule JunctionBoxes do
33
33
+
def all_pairs([]), do: []
34
34
+
35
35
+
def all_pairs([x | rest]) do
36
36
+
for(y <- rest, do: {x, y}) ++ all_pairs(rest)
37
37
+
end
38
38
+
39
39
+
def dist2({ax, ay, az}, {bx, by, bz}) do
40
40
+
dx = ax - bx
41
41
+
dy = ay - by
42
42
+
dz = az - bz
43
43
+
44
44
+
dx ** 2 + dy ** 2 + dz ** 2
45
45
+
end
46
46
+
47
47
+
def group([], {a, b}), do: [MapSet.new([a, b])]
48
48
+
def group([set | rest], {a, b}) do
49
49
+
cond do
50
50
+
a in set and b in set -> [set | rest]
51
51
+
a in set or b in set -> set |> MapSet.put(a) |> MapSet.put(b) |> do_squash(rest, a, b, [])
52
52
+
true -> [set | group(rest, {a, b})]
53
53
+
end
54
54
+
end
55
55
+
56
56
+
defp do_squash(curr, [], _, _, acc), do: [curr | acc]
57
57
+
defp do_squash(curr, [x | rest], a, b, acc) do
58
58
+
if a in x or b in x do
59
59
+
[MapSet.union(curr, x) | acc ++ rest]
60
60
+
else
61
61
+
do_squash(curr, rest, a, b, [x | acc])
62
62
+
end
63
63
+
end
64
64
+
end
65
65
+
```
66
66
+
67
67
+
```elixir
68
68
+
sorted_pairs =
69
69
+
JunctionBoxes.all_pairs(boxes)
70
70
+
|> Enum.sort_by(fn {a, b} -> JunctionBoxes.dist2(a, b) end)
71
71
+
```
72
72
+
73
73
+
<!-- livebook:{"branch_parent_index":1} -->
74
74
+
75
75
+
## Part 1
76
76
+
77
77
+
```elixir
78
78
+
sorted_pairs
79
79
+
|> Enum.take(1000)
80
80
+
|> Enum.reduce([], &JunctionBoxes.group(&2, &1))
81
81
+
|> Enum.map(&MapSet.size/1)
82
82
+
|> Enum.sort(:desc)
83
83
+
|> Enum.take(3)
84
84
+
|> Enum.product()
85
85
+
```
86
86
+
87
87
+
<!-- livebook:{"branch_parent_index":1} -->
88
88
+
89
89
+
## Part 2
90
90
+
91
91
+
```elixir
92
92
+
box_count = length(boxes)
93
93
+
```
94
94
+
95
95
+
```elixir
96
96
+
{a, b} =
97
97
+
sorted_pairs
98
98
+
|> Enum.reduce_while([], fn pair, acc ->
99
99
+
new_acc = JunctionBoxes.group(acc, pair)
100
100
+
101
101
+
if MapSet.size(hd(new_acc)) == box_count do
102
102
+
{:halt, pair}
103
103
+
else
104
104
+
{:cont, new_acc}
105
105
+
end
106
106
+
end)
107
107
+
```
108
108
+
109
109
+
```elixir
110
110
+
{ax, _, _} = a
111
111
+
{bx, _, _} = b
112
112
+
113
113
+
ax * bx
114
114
+
```
115
115
+
116
116
+
<!-- livebook:{"offset":2222,"stamp":{"token":"XCP.sY5bJOGXuU_ZotobOVN6-zcg0TDJGEWVaJESs_-qDHzeEplFoStZ8_c6TRpS5eVpqnzoaj-gsLs_drksuYvMCDcM3T7_M6p9s09DRSKgMU2YB_Ogb0CB6_gAZamF2zEIUw","version":2}} -->