day24: much better
This commit is contained in:
parent
35f71f42bc
commit
1bd309732b
166
day24.py
166
day24.py
@ -2,118 +2,39 @@ from tools.aoc import AOCDay
|
|||||||
from typing import Any, List
|
from typing import Any, List
|
||||||
|
|
||||||
|
|
||||||
class ALU:
|
def getTheNumberFast(pushpull, adders, subbers, part2=False):
|
||||||
def __init__(self):
|
if part2:
|
||||||
self.memory = {
|
number_init = [9] + [1] * 13
|
||||||
'w': 0,
|
inc = 1
|
||||||
'x': 0,
|
else:
|
||||||
'y': 0,
|
number_init = [9] * 14
|
||||||
'z': 0
|
inc = - 1
|
||||||
}
|
|
||||||
|
|
||||||
def run(self, instr: List, inp=-1):
|
z = int(1e9)
|
||||||
for c in instr:
|
number = number_init.copy()
|
||||||
if c[0] == "inp":
|
while z > 0:
|
||||||
self.memory[c[1]] = inp
|
z = 0
|
||||||
elif c[0] == "add":
|
down = False
|
||||||
if c[2] in "wxyz":
|
for i, inp in enumerate(number.copy()):
|
||||||
self.memory[c[1]] += self.memory[c[2]]
|
if pushpull[i]:
|
||||||
else:
|
z = z * 26 + adders[i] + inp
|
||||||
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:
|
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'):
|
return int("".join(map(str, number)))
|
||||||
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):
|
class Day(AOCDay):
|
||||||
@ -133,10 +54,31 @@ class Day(AOCDay):
|
|||||||
|
|
||||||
return instructions
|
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:
|
def part1(self) -> Any:
|
||||||
instr = self.getDigitInstr()
|
pushpull, adders, subbers = self.getInputNumbers()
|
||||||
return getTheNumber(instr)
|
return getTheNumberFast(pushpull, adders, subbers)
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
instr = self.getDigitInstr()
|
pushpull, adders, subbers = self.getInputNumbers()
|
||||||
return getTheNumber(instr, 'min')
|
return getTheNumberFast(pushpull, adders, subbers, part2=True)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user