diff --git a/day24.py b/day24.py index 3b67f99..77ac48b 100644 --- a/day24.py +++ b/day24.py @@ -2,118 +2,39 @@ 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 getTheNumberFast(pushpull, adders, subbers, part2=False): + if part2: + number_init = [9] + [1] * 13 + inc = 1 + else: + number_init = [9] * 14 + inc = - 1 - 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])) + z = int(1e9) + number = number_init.copy() + while z > 0: + z = 0 + down = False + for i, inp in enumerate(number.copy()): + if pushpull[i]: + z = z * 26 + adders[i] + inp else: - raise ValueError("invalid instr", c) + if 0 < z % 26 + subbers[i] < 10: + number[i] = z % 26 + subbers[i] + else: + for j in range(i - 1, -1, -1): + if pushpull[j] and 0 < number[j] + inc < 10: + number[j] += inc + for k in range(j + 1, 14): + number[k] = number_init[k] + down = True + break + z //= 26 + if down: + break -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 - ) + return int("".join(map(str, number))) class Day(AOCDay): @@ -133,10 +54,31 @@ class Day(AOCDay): return instructions + def getInputNumbers(self): + pushpull = [] + adders = [] + subbers = [] + next_add = False + for line in self.getInput(): + if line.startswith("div z"): + pushpull.append(line.endswith(" 1")) + + if line.startswith("add x") and line[-1] != "z": + subbers.append(int(line.split()[-1])) + + if line.startswith("add y") and next_add: + adders.append(int(line.split()[-1])) + next_add = False + + if line == "add y w": + next_add = True + + return pushpull, adders, subbers + def part1(self) -> Any: - instr = self.getDigitInstr() - return getTheNumber(instr) + pushpull, adders, subbers = self.getInputNumbers() + return getTheNumberFast(pushpull, adders, subbers) def part2(self) -> Any: - instr = self.getDigitInstr() - return getTheNumber(instr, 'min') + pushpull, adders, subbers = self.getInputNumbers() + return getTheNumberFast(pushpull, adders, subbers, part2=True)