Advent of Code 2023 - Day 08
Mix.install([
{:kino, "~> 0.11.0"},
{:kino_aoc, github: "ljgago/kino_aoc"}
])
Input
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2023", "8", System.fetch_env!("LB_AOC_SESSION"))
[first | rest] = String.split(puzzle_input, "\n", trim: true)
instructions = String.split(first, "", trim: true)
network =
rest
|> Enum.map(fn line ->
Regex.scan(~r/([A-Z]){3}/, line, capture: :first)
|> List.flatten()
end)
|> Map.new(fn [k, l, r] -> {k, %{"L" => l, "R" => r}} end)
Part 1
count_steps_while = fn start, while_fun ->
instructions
|> Stream.cycle()
|> Enum.reduce_while({0, start}, fn instruction, {count, next} ->
steps = count + 1
next = network[next][instruction]
if while_fun.(next), do: {:halt, steps}, else: {:cont, {steps, next}}
end)
end
count_steps_while.("AAA", &String.equivalent?(&1, "ZZZ"))
Part 2
network
|> Map.keys()
|> Enum.filter(&String.ends_with?(&1, "A"))
|> Enum.map(fn start -> count_steps_while.(start, &String.ends_with?(&1, "Z")) end)
|> Enum.reduce(fn a, b -> div(a * b, Integer.gcd(a, b)) end)