from tools.aoc import AOCDay from typing import Any, List class ALU: def __init__(self): self.memory = { 'w': 0, 'x': 0, 'y': 0, 'z': 0 } def run(self, instr: List, inp=-1): for c in instr: if c[0] == "inp": self.memory[c[1]] = inp elif c[0] == "add": if c[2] in "wxyz": self.memory[c[1]] += self.memory[c[2]] else: self.memory[c[1]] += int(c[2]) elif c[0] == "mul": if c[2] in "wxyz": self.memory[c[1]] *= self.memory[c[2]] else: self.memory[c[1]] *= int(c[2]) elif c[0] == "div": if c[2] in "wxyz": self.memory[c[1]] //= self.memory[c[2]] else: self.memory[c[1]] //= int(c[2]) elif c[0] == "mod": if c[2] in "wxyz": self.memory[c[1]] %= self.memory[c[2]] else: self.memory[c[1]] %= int(c[2]) elif c[0] == "eql": if c[2] in "wxyz": self.memory[c[1]] = int(self.memory[c[1]] == self.memory[c[2]]) else: self.memory[c[1]] = int(self.memory[c[1]] == int(c[2])) else: raise ValueError("invalid instr", c) def getTheNumber(instr, what='max'): lower = 9 upper = 0 step = -1 if what != 'max': lower = 1 upper = 10 step = 1 for inp0 in range(9, upper, step): # the 9 should be "lower", but Eric being Eric ... you get the point for inp1 in range(lower, upper, step): for inp2 in range(lower, upper, step): for inp4 in range(lower, upper, step): for inp5 in range(lower, upper, step): for inp7 in range(lower, upper, step): for inp9 in range(lower, upper, step): alu = ALU() alu.run(instr[0], inp0) alu.run(instr[1], inp1) alu.run(instr[2], inp2) inp3 = alu.memory['z'] % 26 - 8 if not 0 < inp3 < 10: continue alu.run(instr[3], inp3) alu.run(instr[4], inp4) alu.run(instr[5], inp5) inp6 = alu.memory['z'] % 26 - 11 if not 0 < inp6 < 10: continue alu.run(instr[6], inp6) alu.run(instr[7], inp7) inp8 = alu.memory['z'] % 26 - 3 if not 0 < inp8 < 10: continue alu.run(instr[8], inp8) alu.run(instr[9], inp9) inp10 = alu.memory['z'] % 26 - 3 if not 0 < inp10 < 10: continue alu.run(instr[10], inp10) inp11 = alu.memory['z'] % 26 - 1 if not 0 < inp11 < 10: continue alu.run(instr[11], inp11) inp12 = alu.memory['z'] % 26 - 10 if not 0 < inp12 < 10: continue alu.run(instr[12], inp12) inp13 = alu.memory['z'] - 16 if not 0 < inp13 < 10: continue alu.run(instr[13], inp13) if alu.memory['z'] == 0: return ( inp0 * 10_000_000_000_000 + inp1 * 1_000_000_000_000 + inp2 * 100_000_000_000 + inp3 * 10_000_000_000 + inp4 * 1_000_000_000 + inp5 * 100_000_000 + inp6 * 10_000_000 + inp7 * 1_000_000 + inp8 * 100_000 + inp9 * 10_000 + inp10 * 1_000 + inp11 * 100 + inp12 * 10 + inp13 ) class Day(AOCDay): test_solutions_p1 = [99598963999971] test_solutions_p2 = [93151411711211] def getDigitInstr(self): instructions = [] this_instr = [] for instr in self.getInputAsArraySplit(" "): if instr[0] == "inp" and this_instr: instructions.append(this_instr) this_instr = [] this_instr.append(instr) instructions.append(this_instr) return instructions def part1(self) -> Any: instr = self.getDigitInstr() return getTheNumber(instr) def part2(self) -> Any: instr = self.getDigitInstr() return getTheNumber(instr, 'min')