diff --git a/solutions/8/README.md b/solutions/8/README.md new file mode 100644 index 0000000..3dbd044 --- /dev/null +++ b/solutions/8/README.md @@ -0,0 +1,15 @@ +# 8 + +Keep getting better! Today we write a little state machine, love it. + +So firstly we remember what `oc` (Operation Counter) we have already visited and if so we simply stop and return the accumulator. + +For I basically run the code many times, inverting `nop` to `jmp` and vice versa until i found a working instruction set. + +
+ Solutions +
    +
  1. 1087
  2. +
  3. 780
  4. +
+
diff --git a/solutions/8/python/main.py b/solutions/8/python/main.py new file mode 100644 index 0000000..b12b270 --- /dev/null +++ b/solutions/8/python/main.py @@ -0,0 +1,63 @@ +from os.path import join, dirname +from typing import List, Optional, Set, Tuple + +Instructions = List[Tuple[str, int]] + + +class VM: + def __init__(self, code: str) -> None: + instructionsRaw = code.strip().split('\n') + self.acc = 0 + self.oc = 0 + self.invert: Optional[int] = None + self.instructions: Instructions = [] + for instruction in instructionsRaw: + op, value = instruction.split(' ') + self.instructions.append((op, int(value))) + + def reset(self): + self.acc = 0 + self.oc = 0 + + def exec(self): + op, value = self.instructions[self.oc] + if self.oc == self.invert: + op = 'jmp' if op == 'nop' else 'nop' + if op == 'nop': + self.oc += 1 + elif op == 'acc': + self.acc += value + self.oc += 1 + elif op == 'jmp': + self.oc += value + + def run(self) -> Tuple[int, bool]: + self.reset() + already_visited: Set[int] = set() + m = len(self.instructions) + while True: + if self.oc in already_visited: + return (self.acc, True) + if not self.oc < m: + return (self.acc, False) + already_visited.add(self.oc) + self.exec() + + def fix(self): + for i, instruction in enumerate(self.instructions): + op, _ = instruction + if op == 'nop' or op == 'jmp': + self.invert = i + acc, error = self.run() + if not error: + return acc + + +data = join(dirname(__file__), '../data.txt') +with open(data) as f: + vm = VM(f.read()) + + acc, err = vm.run() + print(acc) + + print(vm.fix())