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

Advent of Code 2023 Day 8 Part 2

2023_day8_part2.livemd

Advent of Code 2023 Day 8 Part 2

Mix.install([
  {:kino_aoc, "~> 0.1.5"}
])

Get Inputs

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "8", System.fetch_env!("LB_SESSION"))

My answer

defmodule Resolver do
  def parse(input) do
    [instructions | maps] = String.split(input, "\n\n")

    instructions = String.codepoints(instructions)

    maps =
      maps
      |> hd()
      |> String.split("\n")
      |> Enum.into(%{}, fn line ->
        parse_map(line)
      end)

    {instructions, maps}
  end

  defp parse_map(line) do
    [current, left, right] =
      line
      |> String.replace("=", "")
      |> String.replace("(", "")
      |> String.replace(")", "")
      |> String.replace(",", "")
      |> String.split(" ", trim: true)
      |> Enum.map(&String.reverse(&1))

    {current, %{"L" => left, "R" => right}}
  end

  def resolve(instructions, maps) do
    start_points =
      maps
      |> Map.keys()
      |> Enum.filter(fn key ->
        String.starts_with?(key, "A")
      end)

    start_points
    |> Enum.reduce(1, fn start_point, acc ->
      start_point
      |> step(maps, 0, instructions, 0)
      |> lcm(acc)
    end)
  end

  defp step("Z" <> _, _, _, _, acc), do: acc

  defp step(current, maps, inst_index, instructions, acc) do
    instruction = Enum.at(instructions, inst_index)

    next = maps[current][instruction]

    next_inst_index =
      if inst_index == Enum.count(instructions) - 1 do
        0
      else
        inst_index + 1
      end

    step(next, maps, next_inst_index, instructions, acc + 1)
  end

  def lcm(a, b), do: div(a * b, Integer.gcd(a, b))
end
{instructions, maps} =
  """
  LR

  11A = (11B, XXX)
  11B = (XXX, 11Z)
  11Z = (11B, XXX)
  22A = (22B, XXX)
  22B = (22C, 22C)
  22C = (22Z, 22Z)
  22Z = (22B, 22B)
  XXX = (XXX, XXX)
  """
  |> String.slice(0..-2)
  |> Resolver.parse()
Resolver.resolve(instructions, maps)
{instructions, maps} = Resolver.parse(puzzle_input)
Resolver.resolve(instructions, maps)