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

Day 23: Opening the Turing Lock

day_23_opening_the_turing_lock.livemd

Day 23: Opening the Turing Lock

Section

defmodule Computer do
  def run_instructions(instructions, registers \\ %{a: 0, b: 0}) do
    execute(instructions, registers, 0)
  end

  defp execute(instructions, registers, pointer) when pointer >= length(instructions),
    do: registers

  defp execute(instructions, registers, pointer) do
    {new_registers, new_pointer} =
      case Enum.at(instructions, pointer) do
        {:hlf, r} ->
          {Map.update!(registers, r, &div(&1, 2)), pointer + 1}

        {:tpl, r} ->
          {Map.update!(registers, r, &(&1 * 3)), pointer + 1}

        {:inc, r} ->
          {Map.update!(registers, r, &(&1 + 1)), pointer + 1}

        {:jmp, offset} ->
          {registers, pointer + offset}

        {:jie, r, offset} ->
          if rem(Map.get(registers, r), 2) == 0,
            do: {registers, pointer + offset},
            else: {registers, pointer + 1}

        {:jio, r, offset} ->
          if Map.get(registers, r) == 1,
            do: {registers, pointer + offset},
            else: {registers, pointer + 1}
      end

    execute(instructions, new_registers, new_pointer)
  end
end

defmodule InputParser do
  def parse(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.map(&parse_instruction/1)
  end

  defp parse_instruction(line) do
    case String.split(line) do
      ["hlf", r] ->
        {:hlf, String.to_atom(r)}

      ["tpl", r] ->
        {:tpl, String.to_atom(r)}

      ["inc", r] ->
        {:inc, String.to_atom(r)}

      ["jmp", offset] ->
        {:jmp, String.to_integer(offset)}

      ["jie", r, offset] ->
        {:jie, String.to_atom(String.trim_trailing(r, ",")), String.to_integer(offset)}

      ["jio", r, offset] ->
        {:jio, String.to_atom(String.trim_trailing(r, ",")), String.to_integer(offset)}
    end
  end
end

parsed_instructions =
  "/Users/eli/Desktop/input.txt"
  |> File.read!()
  |> InputParser.parse()

Computer.run_instructions(parsed_instructions)
%{a: 1, b: 184}
Computer.run_instructions(parsed_instructions, %{a: 1, b: 0})
%{a: 1, b: 231}