mirror of
https://github.com/cupcakearmy/advent-of-code.git
synced 2025-01-02 21:26:25 +00:00
8
This commit is contained in:
parent
791b94827e
commit
3a302d71c9
15
solutions/8/README.md
Normal file
15
solutions/8/README.md
Normal file
@ -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.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Solutions</summary>
|
||||||
|
<ol>
|
||||||
|
<li>1087</li>
|
||||||
|
<li>780</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
63
solutions/8/python/main.py
Normal file
63
solutions/8/python/main.py
Normal file
@ -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())
|
Loading…
Reference in New Issue
Block a user