Skip to content

Commit ce27247

Browse files
committed
More idiomatic elixir
1 parent b75d656 commit ce27247

File tree

2 files changed

+57
-55
lines changed

2 files changed

+57
-55
lines changed

2025/lib/day08/day08.ex

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
defmodule Day08 do
22
def input(infile) do
3-
File.read!(infile)
4-
|> String.trim()
5-
|> String.split("\n")
6-
|> Enum.map(&String.trim/1)
7-
|> Enum.map(&String.split(&1, ","))
8-
|> Enum.map(fn str ->
9-
Enum.map(str, &String.to_integer/1)
3+
infile
4+
|> File.read!()
5+
|> String.split("\n", trim: true)
6+
|> Enum.map(fn line ->
7+
line
8+
|> String.split(",", trim: true)
9+
|> Enum.map(&String.to_integer/1)
10+
|> List.to_tuple()
1011
end)
11-
|> Enum.map(&List.to_tuple/1)
1212
end
1313

1414
# We skip the sqrt here to save CPU cycles, we still compare apples to apples
15-
def distance(a, b) do
16-
{a_x, a_y, a_z} = a
17-
{b_x, b_y, b_z} = b
18-
x_d = a_x - b_x
19-
y_d = a_y - b_y
20-
z_d = a_z - b_z
21-
Integer.pow(x_d, 2) + Integer.pow(y_d, 2) + Integer.pow(z_d, 2)
15+
def distance({ax, ay, az}, {bx, by, bz}) do
16+
dx = ax - bx
17+
dy = ay - by
18+
dz = az - bz
19+
dx * dx + dy * dy + dz * dz
2220
end
2321

2422
# Hash keyed on edge distance, mapped to a set of two points
@@ -33,12 +31,12 @@ defmodule Day08 do
3331
end
3432

3533
defp points_to_circuits(points) do
36-
MapSet.new(Enum.map(points, fn p -> MapSet.new([p]) end))
34+
points
35+
|> Enum.map(&MapSet.new([&1]))
36+
|> MapSet.new()
3737
end
3838

39-
def connect_points(points, edges, connections) do
40-
circuits = points_to_circuits(points)
41-
39+
def connect_points(circuits, edges, connections) do
4240
Map.keys(edges)
4341
|> Enum.sort()
4442
|> Enum.take(connections)
@@ -47,22 +45,22 @@ defmodule Day08 do
4745
end)
4846
end
4947

50-
def connect_points_edges(circuits, edge) do
51-
{a, b} = edge
52-
53-
{edge_groups, remaining_circuits} =
54-
MapSet.split_with(circuits, fn circuit ->
55-
MapSet.member?(circuit, a) or MapSet.member?(circuit, b)
48+
# Connect to circuits and return the resulting circuit set
49+
# TODO This would be dramatically faster using a disjoint-set union
50+
def connect_points_edges(circuits, {a, b}) do
51+
{edge_groups, remaining} =
52+
MapSet.split_with(circuits, fn group ->
53+
MapSet.member?(group, a) or MapSet.member?(group, b)
5654
end)
5755

58-
new_group = Enum.reduce(edge_groups, &MapSet.union(&2, &1))
59-
MapSet.put(remaining_circuits, new_group)
56+
merged = Enum.reduce(edge_groups, &MapSet.union(&2, &1))
57+
58+
# Dialyzer complains about remaining but I assure you it's a MapSet and is fine
59+
MapSet.put(remaining, merged)
6060
end
6161

6262
# the last connection which causes all of the junction boxes to form a single circuit
63-
def last_connection(points, edges) do
64-
circuits = points_to_circuits(points)
65-
63+
def last_connection(edges, circuits) do
6664
Map.keys(edges)
6765
|> Enum.sort()
6866
|> Enum.reduce_while(circuits, fn edge_d, circ_acc ->
@@ -77,33 +75,37 @@ defmodule Day08 do
7775
end)
7876
end
7977

80-
def part1(infile, connections) do
81-
points = input(infile)
82-
edges = edges(points)
83-
circuits = connect_points(points, edges, connections)
78+
def part1(edges, circuits, connections) do
79+
connected_circuits = connect_points(circuits, edges, connections)
8480

85-
Enum.map(circuits, &MapSet.size/1)
86-
|> Enum.sort()
87-
|> Enum.reverse()
81+
Enum.map(connected_circuits, &MapSet.size/1)
82+
|> Enum.sort(:desc)
8883
|> Enum.take(3)
8984
|> Enum.product()
9085
end
9186

92-
def part2(infile) do
87+
def part2(edges, circuits) do
88+
{{a_x, _, _}, {b_x, _, _}} = last_connection(edges, circuits)
89+
90+
a_x * b_x
91+
end
92+
93+
def loader(infile) do
9394
points = input(infile)
9495
edges = edges(points)
96+
circuits = points_to_circuits(points)
9597

96-
{{a_x, _, _}, {b_x, _, _}} = last_connection(points, edges)
97-
98-
a_x * b_x
98+
{edges, circuits}
9999
end
100100

101101
def main do
102102
input_path = "lib/day08/input.txt"
103103

104-
answer = part1(input_path, 1000)
104+
{edges, circuits} = loader(input_path)
105+
106+
answer = part1(edges, circuits, 1000)
105107
IO.puts("Part 1: #{answer}")
106-
answer = part2(input_path)
108+
answer = part2(edges, circuits)
107109
IO.puts("Part 2: #{answer}")
108110
end
109111
end

2025/test/day08/day08_test.exs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,23 @@ defmodule Day08Test do
5050
end
5151

5252
test "connect_points", %{temp_file: temp_file} do
53-
points = Day08.input(temp_file)
54-
edges = Day08.edges(points)
53+
{e, c} = Day08.loader(temp_file)
5554

5655
# Connects the closest circuits into one group
57-
circuits = Day08.connect_points(points, edges, 1)
56+
circuits = Day08.connect_points(c, e, 1)
5857
assert MapSet.size(circuits) == 19
5958

6059
assert MapSet.member?(circuits, MapSet.new([{162, 817, 812}, {425, 690, 689}])) == true
6160

62-
circuits = Day08.connect_points(points, edges, 2)
61+
circuits = Day08.connect_points(c, e, 2)
6362
assert MapSet.size(circuits) == 18
6463

6564
assert MapSet.member?(
6665
circuits,
6766
MapSet.new([{162, 817, 812}, {425, 690, 689}, {431, 825, 988}])
6867
) == true
6968

70-
circuits = Day08.connect_points(points, edges, 3)
69+
circuits = Day08.connect_points(c, e, 3)
7170
assert MapSet.size(circuits) == 17
7271

7372
assert MapSet.member?(
@@ -76,24 +75,25 @@ defmodule Day08Test do
7675
) == true
7776

7877
# The next two junction boxes are 431,825,988 and 425,690,689. Because these two junction boxes were already in the same circuit, nothing happens!
79-
circuits = Day08.connect_points(points, edges, 4)
78+
circuits = Day08.connect_points(c, e, 4)
8079
assert MapSet.size(circuits) == 17
8180

82-
circuits = Day08.connect_points(points, edges, 10)
81+
circuits = Day08.connect_points(c, e, 10)
8382
assert MapSet.size(circuits) == 11
8483
end
8584

8685
test "part1", %{temp_file: temp_file} do
87-
assert Day08.part1(temp_file, 10) == 40
86+
{e, c} = Day08.loader(temp_file)
87+
assert Day08.part1(e, c, 10) == 40
8888
end
8989

9090
test "last_connection", %{temp_file: temp_file} do
91-
points = Day08.input(temp_file)
92-
edges = Day08.edges(points)
93-
assert Day08.last_connection(points, edges) == {{216, 146, 977}, {117, 168, 530}}
91+
{e, c} = Day08.loader(temp_file)
92+
assert Day08.last_connection(e, c) == {{216, 146, 977}, {117, 168, 530}}
9493
end
9594

9695
test "part2", %{temp_file: temp_file} do
97-
assert Day08.part2(temp_file) == 25272
96+
{e, c} = Day08.loader(temp_file)
97+
assert Day08.part2(e, c) == 25272
9898
end
9999
end

0 commit comments

Comments
 (0)