You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
2.0 KiB
79 lines
2.0 KiB
#!/usr/bin/env python3
|
|
|
|
import sys, re, math
|
|
|
|
|
|
out = []
|
|
|
|
|
|
def output(i):
|
|
out.append(i)
|
|
|
|
|
|
def instr(opc, op, ra, rb, rc, p):
|
|
cop = op
|
|
if op in [4,5,6]: cop = [ra,rb,rc][op-4]
|
|
if op == 7: cop = 'ERROR'
|
|
if opc == 0: # 'adv' instruction
|
|
ra = math.trunc(ra / 2**cop)
|
|
p += 2
|
|
elif opc == 1: # 'bxl' instruction
|
|
rb = rb ^ op
|
|
p += 2
|
|
elif opc == 2: # 'bst' instruction
|
|
rb = cop % 8
|
|
p += 2
|
|
elif opc == 3: # 'jnz' instruction
|
|
if ra != 0:
|
|
p = op
|
|
else:
|
|
p += 2
|
|
elif opc == 4: # 'bxc' instruction
|
|
rb = rb ^ rc
|
|
p += 2
|
|
elif opc == 5: # 'out' instruction
|
|
output(cop % 8)
|
|
p += 2
|
|
elif opc == 6: # 'bdv' instruction
|
|
rb = math.trunc(ra / 2**cop)
|
|
p += 2
|
|
elif opc == 7: # 'cdv' instruction
|
|
rc = math.trunc(ra / 2**cop)
|
|
p += 2
|
|
return ra, rb, rc, p
|
|
|
|
|
|
def step(lb, ub, i, exp):
|
|
for ra in range(lb, ub):
|
|
if (((ra//8**i)%8) ^ 1 ^ int((ra//8**i) / 2**((ra//8** i%8)^2)) % 8) == exp: yield ra
|
|
|
|
|
|
if __name__ == '__main__':
|
|
ins = open(sys.argv[1]).read()
|
|
g = re.search(r'Register A: (?P<ra>\d+)\nRegister B: (?P<rb>\d+)\nRegister C: (?P<rc>\d+)\n\nProgram: (?P<prog>(\d+,?)*)', ins)
|
|
ra, rb, rc = int(g['ra']), int(g['rb']), int(g['rc'])
|
|
prog = [int(p) for p in g['prog'].split(',')]
|
|
pointer = 0
|
|
while True:
|
|
if pointer >= len(prog): break
|
|
ra, rb, rc, pointer = instr(prog[pointer], prog[pointer+1], ra, rb, rc, pointer)
|
|
|
|
possible_bounds = [(0,8)]
|
|
for i in range(15,-1,-1):
|
|
exp = prog[i]
|
|
possible_x = []
|
|
for lb, ub in possible_bounds:
|
|
possible_x += [i for i in step(lb, ub, 0, exp)]
|
|
possible_bounds = [(x*8,(x+1)*8) for x in possible_x]
|
|
ra = min(possible_x)
|
|
|
|
|
|
|
|
# challenge 1
|
|
res1 = ','.join([str(o) for o in out])
|
|
print(f"challenge 1:\n{res1}\n")
|
|
|
|
# challenge 2
|
|
res2 = ra
|
|
print(f"challenge 2 (only works for my input):\n{res2}")
|
|
|
|
|