Skip to content

Commit 7db283d

Browse files
committed
Solve 2018-25
1 parent 47aab7c commit 7db283d

3 files changed

Lines changed: 1357 additions & 0 deletions

File tree

lib/2018/day_25.ex

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
defmodule AdventOfCode.Y2018.Day25 do
2+
@moduledoc """
3+
--- Day 25: Four-Dimensional Adventure ---
4+
Problem Link: https://adventofcode.com/2018/day/25
5+
Difficulty: m
6+
Tags: graph connectivity constellation
7+
"""
8+
alias AdventOfCode.Helpers.{InputReader, Transformers}
9+
alias Yog.Connectivity
10+
11+
def input, do: InputReader.read_from_file(2018, 25)
12+
13+
def run(input \\ input()) do
14+
points = parse(input)
15+
16+
{run_1(points), run_2(points)}
17+
end
18+
19+
defp run_1(points) do
20+
# Points form "constellations" if their Manhattan distance is <= 3.
21+
# This is exactly finding connected components in a graph where
22+
# nodes are points and edges connect points with distance <= 3.
23+
graph = build_graph(points)
24+
25+
Connectivity.connected_components(graph)
26+
|> length()
27+
end
28+
29+
defp run_2(_points) do
30+
"Finished the 4D adventure! 🥳"
31+
end
32+
33+
defp build_graph(points_with_index) do
34+
# Each points has an index for stable node ID.
35+
points =
36+
points_with_index
37+
|> Enum.with_index()
38+
39+
# Create the undirected graph with nodes.
40+
initial_graph =
41+
Enum.reduce(points, Yog.undirected(), fn {p, idx}, acc ->
42+
Yog.add_node(acc, idx, p)
43+
end)
44+
45+
# Consider all pairs of points and add edges if they are connected.
46+
# O(N^2) checks. N ~ 1250 => ~780k checks.
47+
# We only check each pair once.
48+
add_edges(points, initial_graph)
49+
end
50+
51+
defp add_edges([], graph), do: graph
52+
53+
defp add_edges([{p1, i1} | rest], graph) do
54+
new_graph =
55+
Enum.reduce(rest, graph, fn {p2, i2}, acc ->
56+
if manhattan_dist(p1, p2) <= 3 do
57+
# Graph is undirected, so order doesn't matter.
58+
# add_edge! ensures we don't handle error tuples inside the loop.
59+
Yog.add_edge!(acc, from: i1, to: i2, with: 1)
60+
else
61+
acc
62+
end
63+
end)
64+
65+
add_edges(rest, new_graph)
66+
end
67+
68+
defp manhattan_dist({x1, y1, z1, w1}, {x2, y2, z2, w2}) do
69+
abs(x1 - x2) + abs(y1 - y2) + abs(z1 - z2) + abs(w1 - w2)
70+
end
71+
72+
def parse(data \\ input()) do
73+
for line <- Transformers.lines(data) do
74+
line
75+
|> String.split(",")
76+
|> Enum.map(&String.trim/1)
77+
|> Enum.map(&String.to_integer/1)
78+
|> List.to_tuple()
79+
end
80+
end
81+
end

0 commit comments

Comments
 (0)