Skip to content

Instantly share code, notes, and snippets.

@ynonp
Created December 8, 2020 14:28
Show Gist options
  • Save ynonp/1aae367c87c277815360f8ca7d9479b4 to your computer and use it in GitHub Desktop.
Save ynonp/1aae367c87c277815360f8ca7d9479b4 to your computer and use it in GitHub Desktop.
defmodule VM do
defstruct [:ip, :code, :acc]
end
defmodule Day8 do
def read_input do
File.read!("input/day8.txt")
|> String.split("\n", trim: true)
|> Enum.map(&(String.split(&1, " ", trim: true)))
|> Enum.map(fn [action, param] -> { action, String.to_integer(param) } end)
end
def run_until_loop(vm, seen \\ MapSet.new()) do
if MapSet.member?(seen, vm.ip) do
vm
else
run_until_loop(step(vm), MapSet.put(seen, vm.ip))
end
end
def step(%VM{ip: ip, code: code, acc: acc}) do
case Enum.at(code, ip) do
{ "nop", p } -> %VM{ip: ip + 1, code: code, acc: acc }
{ "acc", p } -> %VM{ip: ip + 1, code: code, acc: acc + p}
{ "jmp", p } -> %VM{ip: ip + p, code: code, acc: acc }
nil -> IO.puts(acc)
end
end
def swap_instruction(code, index) do
case Enum.at(code, index) do
{ "nop", param } -> List.replace_at(code, index, { "jmp", param })
{ "jmp", param } -> List.replace_at(code, index, { "nop", param })
_ -> code
end
end
def part1 do
code = read_input()
vm = %VM{ip: 0, code: code, acc: 0}
result = run_until_loop(vm)
IO.inspect(result.acc)
end
def part2 do
original_code = read_input()
lines = Enum.count(original_code)
vms = for i <- 0..lines do
%VM{ip: 0, acc: 0, code: swap_instruction(original_code, i)}
end
|> Enum.uniq
vms
|> Enum.each(fn vm -> run_until_loop(vm) end)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment