Powered by AppSignal & Oban Pro

Day 24

2021/day24.livemd

Day 24

Section

defmodule Day24 do
  def parse("inp " <> reg), do: {:inp, String.to_atom(reg)}

  def parse(<> <> " " <> <> <> " " <> arg) do
    {String.to_atom(op), String.to_atom(<>), parse_arg(arg)}
  end

  defp parse_arg(arg) do
    case Integer.parse(arg) do
      {num, ""} -> num
      :error -> String.to_atom(arg)
    end
  end

  def evaluate(ops, input), do: evaluate(ops, to_digits(input), %{w: 0, x: 0, y: 0, z: 0})

  defp evaluate([], _, regs), do: regs

  defp evaluate([{:inp, reg} | rest], [v | input], regs),
    do: evaluate(rest, input, %{regs | reg => v})

  defp evaluate([{:eql, reg, v} | rest], input, regs) do
    val = if get(reg, regs) == get(v, regs), do: 1, else: 0

    evaluate(rest, input, %{regs | reg => val})
  end

  defp evaluate([{:add, reg, v} | rest], input, regs),
    do: evaluate(rest, input, %{regs | reg => get(reg, regs) + get(v, regs)})

  defp evaluate([{:mul, reg, v} | rest], input, regs),
    do: evaluate(rest, input, %{regs | reg => get(reg, regs) * get(v, regs)})

  defp evaluate([{:div, reg, v} | rest], input, regs),
    do: evaluate(rest, input, %{regs | reg => div(get(reg, regs), get(v, regs))})

  defp evaluate([{:mod, reg, v} | rest], input, regs),
    do: evaluate(rest, input, %{regs | reg => rem(get(reg, regs), get(v, regs))})

  defp get(imm, _regs) when is_integer(imm), do: imm
  defp get(reg, regs) when is_atom(reg), do: Map.get(regs, reg, 0)

  defp to_digits(int) when is_integer(int), do: Integer.digits(int)
  defp to_digits(digits) when is_list(digits), do: digits
end

input =
  File.stream!("#{__DIR__}/day24.txt")
  |> Stream.map(&amp;String.trim/1)
  |> Enum.map(&amp;Day24.parse/1)
  |> IO.inspect(limit: :infinity)

length(input)
[
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 1},
  {:add, :x, 11},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 16},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 1},
  {:add, :x, 12},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 11},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 1},
  {:add, :x, 13},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 12},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 26},
  {:add, :x, -5},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 12},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 26},
  {:add, :x, -3},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 12},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 1},
  {:add, :x, 14},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 2},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 1},
  {:add, :x, 15},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 11},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 26},
  {:add, :x, -16},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 4},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 1},
  {:add, :x, 14},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 12},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 1},
  {:add, :x, 15},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 9},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 26},
  {:add, :x, -7},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 10},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 26},
  {:add, :x, -11},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 11},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 26},
  {:add, :x, -6},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 6},
  {:mul, :y, :x},
  {:add, :z, :y},
  {:inp, :w},
  {:mul, :x, 0},
  {:add, :x, :z},
  {:mod, :x, 26},
  {:div, :z, 26},
  {:add, :x, -11},
  {:eql, :x, :w},
  {:eql, :x, 0},
  {:mul, :y, 0},
  {:add, :y, 25},
  {:mul, :y, :x},
  {:add, :y, 1},
  {:mul, :z, :y},
  {:mul, :y, 0},
  {:add, :y, :w},
  {:add, :y, 15},
  {:mul, :y, :x},
  {:add, :z, :y}
]
252
digits =
  Enum.chunk_while(
  input,
  [],
  fn
    {:inp, _} = inp, [] -> {:cont, [inp]}
    {:inp, _} = inp, acc -> {:cont, Enum.reverse(acc), [inp]}
    other, acc -> {:cont, [other | acc]}
  end,
  fn acc -> {:cont, Enum.reverse(acc), []} end
)
[
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 1},
    {:add, :x, 11},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 16},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 1},
    {:add, :x, 12},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 11},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 1},
    {:add, :x, 13},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 12},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 26},
    {:add, :x, -5},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 12},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 26},
    {:add, :x, -3},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 12},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 1},
    {:add, :x, 14},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 2},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 1},
    {:add, :x, 15},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 11},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 26},
    {:add, :x, -16},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 4},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 1},
    {:add, :x, 14},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 12},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 1},
    {:add, :x, 15},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 9},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 26},
    {:add, :x, -7},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 10},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 26},
    {:add, :x, -11},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 11},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 26},
    {:add, :x, -6},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 6},
    {:mul, :y, :x},
    {:add, :z, :y}
  ],
  [
    {:inp, :w},
    {:mul, :x, 0},
    {:add, :x, :z},
    {:mod, :x, 26},
    {:div, :z, 26},
    {:add, :x, -11},
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w},
    {:add, :y, 15},
    {:mul, :y, :x},
    {:add, :z, :y}
  ]
]
List.myers_difference(hd(digits), Enum.at(digits, 4))
[
  eq: [{:inp, :w}, {:mul, :x, 0}, {:add, :x, :z}, {:mod, :x, 26}],
  del: [{:div, :z, 1}, {:add, :x, 11}],
  ins: [{:div, :z, 26}, {:add, :x, -3}],
  eq: [
    {:eql, :x, :w},
    {:eql, :x, 0},
    {:mul, :y, 0},
    {:add, :y, 25},
    {:mul, :y, :x},
    {:add, :y, 1},
    {:mul, :z, :y},
    {:mul, :y, 0},
    {:add, :y, :w}
  ],
  del: [{:add, :y, 16}],
  ins: [{:add, :y, 12}],
  eq: [{:mul, :y, :x}, {:add, :z, :y}]
]
params =
  Enum.map(digits, fn sub ->
    [5, 15]
    |> Enum.map(&amp;Enum.at(sub, &amp;1))
    |> Enum.map(&amp;elem(&amp;1, 2))
  end)
[
  [11, 16],
  ~c"\f\v",
  ~c"\r\f",
  [-5, 12],
  [-3, 12],
  [14, 2],
  [15, 11],
  [-16, 4],
  [14, 12],
  [15, 9],
  [-7, 10],
  [-11, 11],
  [-6, 6],
  [-11, 15]
]
defmodule ALU do
  def solve(params, range) do
    params |> solve(0, [], range) |> Enum.reverse() |> Integer.undigits()
  end

  defp solve([], _z, acc, _range), do: acc

  defp solve([[a, b] | rest], z, acc, range) when a > 0 do
    Enum.find_value(range, fn w ->
      solve(rest, 26 * z + w + b, [w | acc], range)
    end)
  end

  defp solve([[a, _] | rest], z, acc, range) when a < 0 do
    value = rem(z, 26) + a

    if value in range do
      solve(rest, div(z, 26), [value | acc], range)
    end
  end
end
{:module, ALU, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:solve, 4}}

Part 1

ALU.solve(params, 9..1//-1)
41299994879959

Part 2

ALU.solve(params, 1..9)
11189561113216