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

Day 20

2022/day20.livemd

Day 20

Mix.install([{:kino, "~>0.8.0"}, {:aja, "~> 0.6.1"}])

Section

file_input = Kino.Input.textarea("file input")

Part 1

alias Aja.Vector

defmodule Day20 do
  def mix(input, n, repeat) do
    1..repeat
    |> Enum.reduce(input, fn _, repeated_acc ->
      0..n
      |> Enum.reduce(repeated_acc, fn i, acc1 ->
        j =
          Enum.reduce_while(0..n, acc1, fn j, acc2 ->
            {_, idx} = acc1[j]

            case idx do
              ^i -> {:halt, j}
              _ -> {:cont, acc2}
            end
          end)

        {val, _} = acc1[j]
        {_, popped} = Vector.pop_at(acc1, j)
        ins = (j + val) |> Integer.mod(n)
        insert_at(popped, ins, {val, i})
      end)
    end)
  end

  def index_of(sequence, n, idx) do
    Enum.reduce_while(0..(n - 1), nil, fn i, acc ->
      case sequence[i] do
        {^idx, _} ->
          {:halt, i}

        _ ->
          {:cont, acc}
      end
    end)
  end

  def grove_sum(sequence, n, zero_idx) do
    [1000, 2000, 3000]
    |> Enum.reduce(0, fn pos, acc ->
      {val, _} = sequence[rem(zero_idx + pos, n + 1)]
      acc + val
    end)
  end

  # Private methods
  defp insert_at(vector, idx, value) do
    {left, right} = Vector.split(vector, idx)
    left |> Vector.concat([value]) |> Vector.concat(right)
  end
end

input =
  file_input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.map(&String.to_integer/1)
  |> Enum.with_index()
  |> Vector.new()

n = Vector.size(input) - 1
sequence = Day20.mix(input, n, 1)
zero_idx = Day20.index_of(sequence, n, 0)
Day20.grove_sum(sequence, n, zero_idx)

Part 2

alias Aja.Vector

input =
  file_input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.map(&String.to_integer/1)
  |> Enum.with_index()
  |> Vector.new()
  |> Vector.map(fn {v, i} -> {v * 811_589_153, i} end)

n = Vector.size(input) - 1
sequence = Day20.mix(input, n, 10)
zero_idx = Day20.index_of(sequence, n, 0)
Day20.grove_sum(sequence, n, zero_idx)