40 lines
1020 B
Elixir
40 lines
1020 B
Elixir
defmodule Aoc2023.Day8 do
|
|
require Integer
|
|
use Aoc2023
|
|
|
|
def parse(input) do
|
|
input
|
|
|> String.split("\n\n")
|
|
|> then(fn [directions, map] ->
|
|
{
|
|
directions |> String.to_charlist() |> Enum.map(&%{?L => 0, ?R => 1}[&1]),
|
|
map
|
|
|> lines
|
|
|> Enum.map(&Regex.run(~r/(\w+) = \((\w+), (\w+)\)/, &1, capture: :all_but_first))
|
|
|> Enum.map(fn [src, dst1, dst2] -> {src, {dst1, dst2}} end)
|
|
|> Enum.into(%{})
|
|
}
|
|
end)
|
|
end
|
|
|
|
defp run({directions, map}, node, filter) do
|
|
directions
|
|
|> Stream.cycle()
|
|
|> Stream.scan(node, fn dir, pos -> map[pos] |> elem(dir) end)
|
|
|> Enum.find_index(filter)
|
|
|> Kernel.+(1)
|
|
end
|
|
|
|
def part1({directions, map}) do
|
|
if map["AAA"], do: run({directions, map}, "AAA", &(&1 == "ZZZ"))
|
|
end
|
|
|
|
def part2({directions, map}) do
|
|
map
|
|
|> Enum.map(pipe(elem(0)))
|
|
|> Enum.filter(pipe(String.ends_with?("A")))
|
|
|> Enum.map(&run({directions, map}, &1, pipe(String.ends_with?("Z"))))
|
|
|> lcm
|
|
end
|
|
end
|