Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Advent of Code 2023 - Day 08

2023/08.livemd

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)

Run in Livebook