def parse_input(file): with open(file, 'r') as f: lines = f.read().strip().split('\n') # Parse register values registers = {} for line in lines[:3]: reg, val = line.split(': ') registers[reg[-1]] = int(val) # Parse program program = [int(x) for x in lines[-1].split(',')] return registers, program class Computer: def __init__(self, registers, program): self.registers = registers.copy() self.program = program self.ip = 0 self.output = [] def get_combo_value(self, operand): if operand <= 3: return operand elif operand <= 6: return self.registers[chr(ord('A') + operand - 4)] return None # operand 7 is reserved def run(self): while self.ip < len(self.program): opcode = self.program[self.ip] operand = self.program[self.ip + 1] if opcode == 0: # adv power = self.get_combo_value(operand) self.registers['A'] //= (2 ** power) elif opcode == 1: # bxl self.registers['B'] ^= operand elif opcode == 2: # bst self.registers['B'] = self.get_combo_value(operand) % 8 elif opcode == 3: # jnz if self.registers['A'] != 0: self.ip = operand continue elif opcode == 4: # bxc self.registers['B'] ^= self.registers['C'] elif opcode == 5: # out value = self.get_combo_value(operand) % 8 self.output.append(str(value)) elif opcode == 6: # bdv power = self.get_combo_value(operand) self.registers['B'] = self.registers['A'] // (2 ** power) elif opcode == 7: # cdv power = self.get_combo_value(operand) self.registers['C'] = self.registers['A'] // (2 ** power) self.ip += 2 return ','.join(self.output) def solve_part1(registers, program): computer = Computer(registers, program) return computer.run() def solve_part2(registers, program): target = ','.join(str(x) for x in program) a = 1 while True: test_registers = registers.copy() test_registers['A'] = a computer = Computer(test_registers, program) output = computer.run() if output == target: return str(a) a += 1 def main(): registers, program = parse_input("./input.txt") # Part 1 print(solve_part1(registers, program)) # Part 2 print(solve_part2(registers, program)) if __name__ == "__main__": main()