We're emulating a simple computer, with 2 registers and 6 instructions. Hardware-emulating puzzles are always the most fun. And so was this one, except for one trick in the instruction. There's an instruction jie - "jump if even", and next one is jio, which I automatically read as "jump if odd", although the instruction explained it's "jump if one". Either I'm dumb or that trick is dumb, you decide.
Other than that, it's simple. Match/case to run the right command and some string parsing. Initial version had 6 more methods, one for each command, but since they were 2-6 lines and even that could be shortened, I moved all of that directly into match/case. To be fair, I could even remove the whole class without affecting the readability too much.
I later learned that Python's match is way more powerful and the code could be shorter and more readable (see 2016 day 12 for comparison), but let's leave it this way.
#!/usr/bin/python3
class Computer:
register: dict = {}
pointer: int
instructions: list
def __init__(self, filename: str) -> None:
with open(filename) as f:
self.instructions = f.read().splitlines()
self.reset()
def reset(self) -> None:
self.register["a"]=0
self.register["b"]=0
self.pointer=0
def __repr__(self) -> str:
return f"Registers: {self.register} pointer {self.pointer} current instruction {self.instructions[self.pointer]}"
def run(self, debug=False) -> None:
while self.pointer<len(self.instructions):
if (debug): print(self)
cmd = self.instructions[self.pointer][:3]
arg = self.instructions[self.pointer][4:]
self.pointer+=1 # will have to decrease by 1 for jumps
match cmd:
case "hlf":
self.register[arg]=self.register[arg]//2
case "tpl":
self.register[arg]*=3
case "inc":
self.register[arg]+=1
case "jmp":
self.pointer+=int(arg)-1
case "jie":
register,offset=arg.split(",")
self.pointer += int(offset) -1 if self.register[register]%2==0 else 0
case "jio":
register,offset=arg.split(",")
self.pointer += int(offset) -1 if self.register[register]==1 else 0
case _: raise ValueError
computer=Computer("23-input.txt")
computer.run()
print("Part 1, register B: ",computer.register["b"])
computer.reset()
computer.register["a"]=1
computer.run()
print("Part 1, register B: ",computer.register["b"])