def run(instructions, a=0, b=0): ip = 0 regs = { 'a': a, 'b': b, } def set(r, v): regs[r] = v return 1 act = { 'hlf': lambda r: set(r, regs[r] // 2), 'tpl': lambda r: set(r, regs[r] * 3), 'inc': lambda r: set(r, regs[r] + 1), 'jmp': lambda offset: offset, 'jie': lambda r, offset: offset if regs[r] % 2 == 0 else 1, 'jio': lambda r, offset: offset if regs[r] == 1 else 1, } while 0 <= ip < len(instructions): ins, ops = instructions[ip] ip += act[ins](*ops) # print(f'ins={ins}, ops={ops}, a={regs["a"]}, b={regs["b"]}, ip={ip}') return regs def part1(instructions): return run(instructions)['b'] def part2(instructons): return run(instructions, 1)['b'] if __name__ == '__main__': with open('input') as f: instructions = list() for line in f: line = line.rstrip() opcode, operands = line.split(' ', maxsplit=1) def parse_operand(s: str) -> int | str: if s[0] == '+': return int(s[1:]) elif s[0] == '-': return -int(s[1:]) return s operands = tuple(parse_operand(op) for op in operands.split(', ')) instructions.append((opcode, operands)) print(part1(instructions)) print(part2(instructions))