75 lines
1.6 KiB
Nim
75 lines
1.6 KiB
Nim
import lib/[loader, util]
|
|
import std/[strutils, sugar]
|
|
|
|
|
|
type
|
|
OpCode = enum
|
|
acc, jmp, nop
|
|
|
|
ProgramLine = object
|
|
op: OpCode
|
|
arg: int
|
|
visited: bool
|
|
|
|
|
|
proc loadProgram(): seq[ProgramLine] =
|
|
for line in loadStrings(8):
|
|
[strOp, strArg] <- line.split()
|
|
let pl = ProgramLine(
|
|
op: parseEnum[OpCode](strOp),
|
|
arg: parseInt(strArg),
|
|
visited: false
|
|
)
|
|
result.add(pl)
|
|
|
|
|
|
proc partOne(prog: seq[ProgramLine]): (int, bool) =
|
|
var prog = prog # mutable copy
|
|
var pos: int
|
|
var accum: int
|
|
while pos < prog.len and not prog[pos].visited:
|
|
prog[pos].visited = true
|
|
let line = prog[pos]
|
|
case line.op
|
|
of acc:
|
|
accum += line.arg
|
|
of jmp:
|
|
pos += line.arg - 1
|
|
of nop:
|
|
discard
|
|
pos += 1
|
|
|
|
if pos == prog.len:
|
|
result = (accum, true)
|
|
else:
|
|
result = (accum, false)
|
|
|
|
|
|
proc partTwo(prog: seq[ProgramLine]): int =
|
|
var prog = prog
|
|
for i, line in prog:
|
|
let orig = line.op
|
|
case line.op
|
|
of acc:
|
|
discard
|
|
of jmp:
|
|
prog[i].op = nop
|
|
of nop:
|
|
prog[i].op = jmp
|
|
|
|
let (accum, finished) = partOne(prog)
|
|
if finished:
|
|
return accum
|
|
prog[i].op = orig
|
|
|
|
raise newException(ValueError, "Couldn't find a working variation.")
|
|
|
|
|
|
when isMainModule:
|
|
let program = loadProgram()
|
|
let (accum, finished) = partOne(program)
|
|
echo "One: ", accum
|
|
echo "Two: ", partTwo(program)
|
|
|
|
|