AoC 2023 - Day 08
Mix.install([
{:kino, "~> 0.11.3"}
])
Section
input_e1 =
"day08-e1.txt"
|> Kino.FS.file_path()
|> File.read!()
|> String.trim()
input_e2 =
"day08-e2.txt"
|> Kino.FS.file_path()
|> File.read!()
|> String.trim()
input_e3 =
"day08-e3.txt"
|> Kino.FS.file_path()
|> File.read!()
|> String.trim()
input =
"day08.txt"
|> Kino.FS.file_path()
|> File.read!()
|> String.trim()
[input_e1, input_e2, input_e3, input]
defmodule SolutionA do
def part_1(input) do
[directions, nodes] = parse(input)
traverse(nodes, directions)
end
def traverse(nodes, directions, steps \\ [], next \\ "AAA", counter \\ 0)
def traverse(_nodes, _directions, _steps, "ZZZ", counter), do: counter
def traverse(nodes, directions, [], next, counter) do
traverse(nodes, directions, directions, next, counter)
end
def traverse(nodes, directions, ["L" | steps], next, counter) do
[next_node, _] = nodes[next]
traverse(nodes, directions, steps, next_node, counter + 1)
end
def traverse(nodes, directions, ["R" | steps], next, counter) do
[_, next_node] = nodes[next]
traverse(nodes, directions, steps, next_node, counter + 1)
end
def parse(input) do
[direction, nodes] = String.split(input, "\n\n")
direction = String.graphemes(direction)
nodes = nodes |> String.split("\n") |> Enum.map(&build/1) |> Map.new()
[direction, nodes]
end
def build(
<>
),
do: {key, [l, r]}
end
defmodule SolutionB do
def part_2(input) do
[directions, nodes] = SolutionA.parse(input)
nodes
|> Map.keys()
|> Enum.filter(&String.ends_with?(&1, "A"))
|> Enum.map(&traverse(nodes, directions, [], &1))
|> Enum.reduce(1, &div(&1 * &2, Integer.gcd(&1, &2)))
end
def traverse(nodes, directions, steps, next, counter \\ 0)
def traverse(_nodes, _directions, _steps, <<_::binary-size(2), next::binary-size(1)>>, counter)
when next == "Z",
do: counter
def traverse(nodes, directions, [], next, counter) do
traverse(nodes, directions, directions, next, counter)
end
def traverse(nodes, directions, [step | steps], next, counter) do
next_node = next_node(nodes[next], step)
traverse(nodes, directions, steps, next_node, counter + 1)
end
def next_node([node, _], "L"), do: node
def next_node([_, node], "R"), do: node
end
SolutionA.part_1(input)
SolutionB.part_2(input)