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)