-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path23.exs
84 lines (77 loc) · 2.31 KB
/
23.exs
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
74
75
76
77
78
79
80
81
82
83
84
defmodule TwentyThree do
def part_one(input) do
input
|> parse()
|> Enum.reduce(%{}, fn {a, b}, acc ->
acc
|> Map.update(a, MapSet.new([b]), &MapSet.put(&1, b))
|> Map.update(b, MapSet.new([a]), &MapSet.put(&1, a))
end)
|> triples()
|> Enum.count(&Enum.any?(&1, fn x -> String.first(x) == "t" end))
end
def part_two(input) do
conn_map =
input
|> parse()
|> Enum.reduce(%{}, fn {a, b}, acc ->
acc
|> Map.update(a, MapSet.new([b]), &MapSet.put(&1, b))
|> Map.update(b, MapSet.new([a]), &MapSet.put(&1, a))
end)
conn_map
|> triples()
|> Stream.iterate(fn set ->
next = wumbo(set, conn_map)
IO.inspect(MapSet.size(next))
next
end)
|> Enum.find(&MapSet.size(&1) == 1)
|> Enum.sort()
|> Enum.join(",")
end
defp parse(text) do
text
|> String.trim()
|> String.split(~r/\R/)
|> Enum.map(fn line ->
String.split(line, "-")
|> List.to_tuple()
end)
end
defp triples(map), do: triples(Enum.to_list(map), MapSet.new())
defp triples([_], acc), do: acc
defp triples([{x, x_conns} | rest], acc) do
new_acc =
Enum.reduce(x_conns, acc, fn y, acc2 ->
case Enum.find(rest, fn {k, _} -> k == y end) do
nil -> acc2
{^y, y_conns} ->
MapSet.intersection(x_conns, y_conns)
|> Enum.map(&MapSet.new([x, y, &1]))
|> Enum.reduce(acc2, fn triple, acc3 -> MapSet.put(acc3, triple) end)
end
end)
triples(rest, new_acc)
end
defp wumbo(groups, conns), do: wumbo(Enum.to_list(groups), conns, MapSet.new())
defp wumbo([_], _, acc), do: acc
defp wumbo([g1 | rest], conns, acc) do
new_acc =
Enum.reduce(rest, acc, fn g2, acc2 ->
with gu <- MapSet.union(g1, g2),
true <- MapSet.size(gu) == MapSet.size(g1) + 1,
c1 <- MapSet.difference(gu, g2) |> Enum.at(0),
c2 <- MapSet.difference(gu, g1) |> Enum.at(0),
true <- conns[c1] |> MapSet.member?(c2) do
MapSet.put(acc2, gu)
else
false -> acc2
end
end)
wumbo(rest, conns, new_acc)
end
end
input = File.read!("input/23.txt")
input |> TwentyThree.part_one() |> IO.inspect(label: "part 1")
input |> TwentyThree.part_two() |> IO.inspect(label: "part 2")