-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathday_12.ex
73 lines (62 loc) · 1.86 KB
/
day_12.ex
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
defmodule AdventOfCode.Y2017.Day12 do
@moduledoc """
--- Day 12: Digital Plumber ---
Problem Link: https://adventofcode.com/2017/day/12
Difficulty: s
Tags: disjoint-set
"""
alias AdventOfCode.Algorithms.DisjointSet
alias AdventOfCode.Helpers.{InputReader, Transformers}
def input, do: InputReader.read_from_file(2017, 12)
def run(input \\ input()) do
disjoint_set = input |> parse() |> create_disjoint_set()
nodes = Map.keys(disjoint_set.parents)
{run_1(disjoint_set, nodes), run_2(disjoint_set, nodes)}
end
defp run_1(disjoint_set, nodes) do
disjoint_set
|> find_connections_for(nodes, 0)
|> length()
end
defp run_2(disjoint_set, nodes) do
disjoint_set
|> find_groups(nodes)
|> Enum.count()
end
defp find_connections_for(disjoint_set, nodes, node) do
{target_parent, disjoint_set} = DisjointSet.find(disjoint_set, node)
nodes
|> Enum.reduce({[], disjoint_set}, fn x, {lst, set} ->
case DisjointSet.find(set, x) do
{^target_parent, new_set} -> {[x | lst], new_set}
{_, new_set} -> {lst, new_set}
end
end)
|> elem(0)
end
defp create_disjoint_set(input) do
disjoint_set = DisjointSet.new(Enum.count(input))
input
|> Enum.reduce(disjoint_set, fn {node, conns}, acc ->
Enum.reduce(conns, acc, fn y, s ->
DisjointSet.union(s, node, y)
end)
end)
end
defp find_groups(disj_set, nodes) do
nodes
|> Enum.reduce({MapSet.new(), disj_set}, fn x, {nodes, set} ->
{parent, new_set} = DisjointSet.find(set, x)
{MapSet.put(nodes, parent), new_set}
end)
|> elem(0)
end
def parse(data \\ input()) do
data
|> Transformers.lines()
|> Map.new(fn line ->
[node, connections] = line |> String.split(" <-> ")
{String.to_integer(node), Transformers.int_words(connections, ", ")}
end)
end
end