79 lines
1.8 KiB
Elixir
79 lines
1.8 KiB
Elixir
defmodule Mix.Tasks.Day8 do
|
|
use Mix.Task
|
|
defp instruction_to_index("L"), do: 0
|
|
defp instruction_to_index("R"), do: 1
|
|
|
|
def walk(_, _, step, <<_::16>> <> "Z") do
|
|
step
|
|
end
|
|
|
|
def walk(instructions, nodes, step, current_location) do
|
|
l =
|
|
instructions
|
|
|> String.graphemes()
|
|
|> Enum.at(rem(step, String.length(instructions)))
|
|
|
|
index = instruction_to_index(l)
|
|
new_location = elem(Map.get(nodes, current_location), index)
|
|
walk(instructions, nodes, step + 1, new_location)
|
|
end
|
|
|
|
def loop_receive(max_len, acc) do
|
|
cond do
|
|
acc |> Enum.count() == max_len -> acc
|
|
true -> receive do
|
|
n -> loop_receive(max_len,[n | acc])
|
|
end
|
|
end
|
|
end
|
|
|
|
def solve(input, _) do
|
|
[instructions, nodes] = input |> String.split("\n\n")
|
|
|
|
nodes =
|
|
for {key, steps} <-
|
|
nodes
|
|
|> String.split("\n")
|
|
|> Stream.reject(&(&1 == ""))
|
|
|> Stream.map(&String.split(String.trim(&1), " = "))
|
|
|> Stream.map(
|
|
&{
|
|
&1 |> Enum.at(0),
|
|
Regex.replace(~r/[\(\)]/, &1 |> Enum.at(1), "")
|
|
|> String.split(", ")
|
|
|> List.to_tuple()
|
|
}
|
|
),
|
|
into: %{} do
|
|
{key, steps}
|
|
end
|
|
|
|
parent = self()
|
|
pids = for entry <- nodes |> Map.keys() |> Enum.filter(&(&1 |> String.ends_with?("A"))) do
|
|
spawn(fn ->
|
|
send(parent,
|
|
walk(
|
|
instructions,
|
|
nodes,
|
|
0,
|
|
entry
|
|
)
|
|
)
|
|
end
|
|
)
|
|
end
|
|
|
|
loop_receive(pids |> Enum.count(), [])
|
|
|> Enum.reduce(
|
|
1,
|
|
fn a, acc ->
|
|
MathUtil.lcm(a, acc)
|
|
end
|
|
) |> IO.puts()
|
|
end
|
|
|
|
def run(_) do
|
|
{_, puzzle_input} = File.read("./input/2023_8.txt")
|
|
solve(puzzle_input, :part2)
|
|
end
|
|
end
|