Advent of Code 2023 - Day 8

Hello, wonderful folks! Ukrainian Erlanger is in the house :metal:! As we bid farewell to the workweek and eagerly await the weekend, we also find ourselves at Day 8 of the captivating Advent of Code. This signifies the arrival of a brand-new puzzle to unravel! I encourage you to share your brilliant code solutions in the comments below. Wishing you all a joyful Friday and, of course, happy coding, folks! :blush:

2 Likes

Day 8

2 Likes

My day 8 solution:

defmodule Aoc.Eight do
  def parse(string) do
    [path, rest] = String.split(string, "\n\n", trim: true)

    map =
      rest
      |> String.split("\n", trim: true)
      |> Enum.map(fn block ->
        [a, b, c] = String.split(block, [" ", "=", "(", ")", ","], trim: true)
        {a, {b, c}}
      end)
      |> Enum.into(%{})

    {path |> String.to_charlist(), map}
  end

  def part_one({path, map} = state) do
    walk_path(path, state, map["AAA"], ["ZZZ"])
  end

  def part_two({path, map} = state) do
    end_nodes = filter_nodes(map, "Z") |> Enum.map(&elem(&1, 0))

    map
    |> filter_nodes("A")
    |> Enum.map(&elem(&1, 1))
    |> Enum.map(&walk_path(path, state, &1, end_nodes))
    |> Enum.reduce(1, &lcm/2)
  end

  def walk_path([], {path, _map} = state, current, end_nodes) do
    walk_path(path, state, current, end_nodes)
  end

  def walk_path([direction | rest], {_path, map} = state, {to_left, to_right}, end_nodes) do
    next =
      case direction do
        ?L -> to_left
        ?R -> to_right
      end

    if Enum.member?(end_nodes, next) do
      1
    else
      1 + walk_path(rest, state, map[next], end_nodes)
    end
  end

  def filter_nodes(map, suffix) do
    Enum.filter(map, fn {node, _} -> String.ends_with?(node, suffix) end)
  end

  def lcm(a, b) do
    div(a * b, Integer.gcd(a, b))
  end
end

input = File.read!("priv/8.txt") |> Aoc.Eight.parse()

input |> Aoc.Eight.part_one() |> IO.inspect(label: "part 1")
input |> Aoc.Eight.part_two() |> IO.inspect(label: "part 2")
1 Like