Skip to content

Instantly share code, notes, and snippets.

@fxn
Last active December 13, 2020 22:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fxn/b9e78e6dddd1cca6952e9e537df865ec to your computer and use it in GitHub Desktop.
Save fxn/b9e78e6dddd1cca6952e9e537df865ec to your computer and use it in GitHub Desktop.
import intsets, strutils, strscans, sequtils
type
Opcode = enum
acc = "acc"
jmp = "jmp"
nop = "nop"
Instruction = tuple
opcode: Opcode
arg: int
RunStatus = enum
InfiniteLoop, Finished
proc parseInstruction(line: string): Instruction =
var
opcode: string
arg: int
if scanf(line, "$w $i", opcode, arg):
result = (parseEnum[Opcode](opcode), arg)
func run(instructions: seq[Instruction]): (RunStatus, int) =
var
ip = 0
totalAcc = 0
visited: IntSet
while true:
if visited.contains(ip):
return (InfiniteLoop, totalAcc)
elif ip >= instructions.len:
return (Finished, totalAcc)
visited.incl(ip)
case instructions[ip].opcode:
of acc:
totalAcc += instructions[ip].arg
ip += 1
of jmp:
ip += instructions[ip].arg
of nop:
ip += 1
var lastMutation = -1
var originalInstructions = toSeq(stdin.lines).map(parseInstruction)
while true:
var instructions = originalInstructions
for i in lastMutation + 1 .. instructions.high:
if instructions[i].opcode == nop:
instructions[i].opcode = jmp
lastMutation = i
break
elif instructions[i].opcode == jmp:
instructions[i].opcode = nop
lastMutation = i
break
let (status, totalAcc) = run(instructions)
if status == Finished:
echo totalAcc
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment