def parse_input(file): with open(file, 'r') as f: lines = f.readlines() initial_values = [int(line.split(': ')[1]) for line in lines[:3]] program = list(map(int, lines[3].split(': ')[1].split(','))) return initial_values, program def get_combo_value(operand, registers): if operand <= 3: return operand elif operand == 4: return registers['A'] elif operand == 5: return registers['B'] elif operand == 6: return registers['C'] else: raise ValueError("Invalid combo operand") def execute_program(registers, program): output = [] ip = 0 while ip < len(program): opcode = program[ip] operand = program[ip + 1] if opcode == 0: # adv denominator = 2 ** get_combo_value(operand, registers) registers['A'] //= denominator elif opcode == 1: # bxl registers['B'] ^= operand elif opcode == 2: # bst registers['B'] = get_combo_value(operand, registers) % 8 elif opcode == 3: # jnz if registers['A'] != 0: ip = operand continue elif opcode == 4: # bxc registers['B'] ^= registers['C'] elif opcode == 5: # out output.append(get_combo_value(operand, registers) % 8) elif opcode == 6: # bdv denominator = 2 ** get_combo_value(operand, registers) registers['B'] = registers['A'] // denominator elif opcode == 7: # cdv denominator = 2 ** get_combo_value(operand, registers) registers['C'] = registers['A'] // denominator ip += 2 return output def part1(file): initial_values, program = parse_input(file) registers = {'A': initial_values[0], 'B': initial_values[1], 'C': initial_values[2]} output = execute_program(registers, program) return ','.join(map(str, output)) def part2(file): _, program = parse_input(file) for a in range(1, 1000000): # Arbitrary large number for search registers = {'A': a, 'B': 0, 'C': 0} output = execute_program(registers, program) if output == program: return a file = "input.txt" print(part1(file)) print(part2(file))