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