Powered by AppSignal & Oban Pro

AoC, Day10

2022/elixir/day10.livemd

AoC, Day10

Mix.install([
  {:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}
])

Setup

{:ok, data} = KinoAOC.download_puzzle("2022", "10", System.fetch_env!("LB_AOC_SECRET"))

Solve

defmodule Day10 do
  @crtlen 40

  def solve(data, opts \\ []) do
    dd = data |> String.split("\n", trim: true) |> Enum.map(&format/1)
    print = Access.get(opts, :print, false)

    # state
    # {reg, cnt, sum_sig, crt}
    crt = build_crt()
    {_, _, r1, crt} = Enum.reduce(dd, {1, 0, 0, crt}, &run_op/2)

    print_crt(crt, print)
    r1
  end

  def build_crt do
    List.duplicate('.', 240)
    |> Enum.with_index(fn el, ind -> {ind, el} end)
    |> Enum.into(%{})
  end

  def print_crt(_, false), do: :noop

  def print_crt(crt, true) do
    crt
    |> Enum.sort_by(fn {ind, _el} -> ind end)
    |> Enum.map(fn {_ind, el} -> el end)
    |> Enum.chunk_every(@crtlen)
    |> Enum.join("\n")
    |> IO.puts()

    :noop
  end

  def run_op(["noop"], state), do: op(state)

  def run_op(["addx", snum], state) do
    state |> op() |> op() |> add_x(snum)
  end

  def op({reg, cnt, sum_sig, crt}) do
    crt = lit_pixel(crt, cnt, reg)
    cnt = cnt + 1
    sig = (rem(cnt, @crtlen) == 20 && reg * cnt) || 0
    {reg, cnt, sum_sig + sig, crt}
  end

  def add_x({reg, cnt, sum_sig, crt}, snum) do
    num = String.to_integer(snum)
    {reg + num, cnt, sum_sig, crt}
  end

  def lit_pixel(crt, cnt, reg) do
    i = rem(cnt, @crtlen)

    if i >= reg - 1 and i <= reg + 1 do
      # #is not clearly visible on this term
      Map.put(crt, cnt, "█")
    else
      Map.put(crt, cnt, " ")
    end
  end

  def format(row) do
    row |> String.trim() |> String.split(" ", trim: true)
  end
end

# 13520
# PGPHBEAB
Day10.solve(data, print: true)

Test

ExUnit.start(autorun: false)

defmodule AoCTest do
  use ExUnit.Case, async: false

  setup do
    dir = System.fetch_env!("LB_INPUTS_DIR")
    d = File.read!(dir <> "/day10t")
    {:ok, %{data: d}}
  end

  test "solves first task", %{data: data} do
    assert 13140 = Day10.solve(data)
  end
end

ExUnit.run()