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

Advent of Code 2022 - Day 10

livebooks/day_10.livemd

Advent of Code 2022 - Day 10

Mix.install([
  {:kino, github: "livebook-dev/kino"}
])

Setup

example_input = """
noop
addx 3
addx -5
"""

input = Kino.Input.textarea("Puzzle Input", default: example_input, monospace: true)

Section

defmodule Instructions do
  def parse(input) do
    input
    |> Kino.Input.read()
    |> String.split("\n", trim: true)
    |> Enum.map(fn
      "noop" -> :noop
      "addx " <> n -> {:addx, String.to_integer(n)}
    end)
  end

  def cycles_stream(instructions) do
    initial_register = 1

    register_value_at_each_cycle =
      Stream.transform(instructions, initial_register, fn
        :noop, register ->
          {[register], register}

        {:addx, value}, register ->
          new_register = register + value
          {[register, new_register], new_register}
      end)

    Stream.concat([initial_register], register_value_at_each_cycle)
  end
end

instructions = Instructions.parse(input)

Part 1

defmodule Part1 do
  def solve(instructions) do
    instructions
    |> Instructions.cycles_stream()
    |> Stream.with_index(1)
    |> Stream.filter(fn {_, index} -> index == 20 or rem(index - 20, 40) == 0 end)
    |> Stream.map(fn {value, index} -> value * index end)
    |> Enum.sum()
  end
end

Part1.solve(instructions)

Part 2

defmodule Part2 do
  def solve(instructions) do
    instructions
    |> Instructions.cycles_stream()
    |> Stream.drop(-1)
    |> Stream.chunk_every(40)
    |> Enum.map_join("\n", fn line ->
      line
      |> Enum.map(&amp;[&amp;1 - 1, &amp;1, &amp;1 + 1])
      |> Enum.with_index()
      |> Enum.map_join(fn {sprite, pixel} ->
        if pixel in sprite do
          "#"
        else
          "."
        end
      end)
    end)
    |> then(fn display ->
      Kino.Markdown.new("""
      ```
      #{display}
      ```
      """)
    end)
  end
end

Part2.solve(instructions)