solve.py (3233B)
1import sys 2sys.path.append("../common") 3import aoc 4 5def parse_log(ls): 6 data = list() 7 before = [int(v) for v in ls[0].split("[")[1].split("]")[0].split(",")] 8 ins = [int(v) for v in ls[1].split(" ")] 9 after = [int(v) for v in ls[2].split("[")[1].split("]")[0].split(",")] 10 return (before, ins, after) 11 12inslog = [] 13data = aoc.data.split("\n") 14progsec = None 15for i in range(0, len(data), 4): 16 if data[i] == "\n": 17 progsec = i 18 break 19 inslog.append(parse_log(data[i:i+4])) 20 21register = list() 22 23opmap = dict() 24opmap["addr"] = lambda a, b : register[a] + register[b] 25opmap["addi"] = lambda a, b : register[a] + b 26opmap["mulr"] = lambda a, b : register[a] * register[b] 27opmap["muli"] = lambda a, b : register[a] * b 28opmap["banr"] = lambda a, b : register[a] & register[b] 29opmap["bani"] = lambda a, b : register[a] & b 30opmap["borr"] = lambda a, b : register[a] | register[b] 31opmap["bori"] = lambda a, b : register[a] | b 32opmap["setr"] = lambda a, b : register[a] 33opmap["seti"] = lambda a, b : a 34opmap["gtir"] = lambda a, b : 1 * (a > register[b]) 35opmap["gtri"] = lambda a, b : 1 * (register[a] > b) 36opmap["gtrr"] = lambda a, b : 1 * (register[a] > register[b]) 37opmap["eqir"] = lambda a, b : 1 * (a == register[b]) 38opmap["eqri"] = lambda a, b : 1 * (register[a] == b) 39opmap["eqrr"] = lambda a, b : 1 * (register[a] == register[b]) 40 41def get_possible(ins): 42 global register 43 sregister = register[:] 44 before = ins[0] 45 after = ins[2] 46 register = before 47 a = ins[1][1] 48 b = ins[1][2] 49 c = ins[1][3] 50 ops = list(opmap.values()) 51 possibles = list() 52 for i in range(len(ops)): 53 op = ops[i] 54 res = None 55 try: 56 res = op(a, b) 57 except: 58 continue 59 if res == after[c]: 60 possibles.append(i) 61 register = sregister 62 return possibles 63 64def solve1(args): 65 global register 66 uncertain = 0 67 for ins in inslog: 68 if len(get_possible(ins)) >= 3: 69 uncertain += 1 70 return uncertain 71 72def solve2(args): 73 possible = dict() 74 for ins in inslog: 75 o = ins[1][0] 76 if o in possible: 77 possible[o] = [op for op in get_possible(ins) if op in possible[o]] 78 else: 79 possible[o] = get_possible(ins) 80 81 certain = False 82 while not certain: 83 singles = [p[0] for p in possible.values() if len(p) == 1] 84 for p in possible: 85 if len(possible[p]) != 1: 86 possible[p] = [v for v in possible[p] if v not in singles] 87 88 certain = True 89 for p in possible.values(): 90 if len(p) != 1: 91 certain = False 92 break 93 94 ntrans = dict() 95 for p in possible: # flatten 96 ntrans[p] = possible[p][0] 97 98 for i in range(progsec, len(data)): # execute program 99 l = data[i] 100 if l == "\n": continue 101 cmd = [int(v) for v in l.split(" ")] 102 while len(register)-1 < cmd[3]: 103 register.append(0) 104 105 register[cmd[3]] = list(opmap.values())[ntrans[cmd[0]]](cmd[1], cmd[2]) 106 107 return register[0] 108 109aoc.run(solve1, solve2, sols=[531, 649])