from lib import get_data from lib import ints LHS, OP, RHS, _, OUT = 0, 1, 2, 3, 4 def run(states, gates): change = True while change: change = False for gate in gates: i1, op, i2, _, out = gate if i1 in states and i2 in states and out not in states: change = True outv = None match op: case "OR": outv = states[i1] | states[i2] case "XOR": outv = states[i1] ^ states[i2] case "AND": outv = states[i1] & states[i2] assert outv is not None states[out] = outv i, t = 0, 0 while True: si = f"z{i:02}" if not si in states: break if states[si]: t += 2**i i += 1 return t data = get_data(__file__) s1, s2 = data.split("\n\n") states = {} for line in s1.splitlines(): gate, value = line.split(": ") states[gate] = int(value) gates = [] out_to_index = {} xors = {} zz = [] for i, line in enumerate(s2.splitlines()): o1, op, o2, _, out = line.split() o1, o2 = sorted([o1, o2]) gate = [o1, op, o2, "->", out] gates.append(gate) out_to_index[out] = i if out.startswith("z"): zz.append(out) if op == "XOR" and o1.startswith("x"): (index,) = ints(o1) xors[index] = gate p1 = run(states, gates) print(p1) NUMBER_Z_GATES = ints(sorted(zz)[-1])[0] + 1 # print(NUMBER_Z_GATES) # pprint(xors) xx = [f"x{i:02}" for i in range(NUMBER_Z_GATES - 1)] yy = [f"y{i:02}" for i in range(NUMBER_Z_GATES - 1)] # def resolve(x): # if x in xx or x in yy: # return f"{x}" # # return x # a, op, b = gate_to_in[x] # aa = resolve(a) # bb = resolve(b) # # print(aa, bb) # aa, bb = sorted([aa, bb], reverse=True) # op = "^" if op == "XOR" else ("|" if op == "OR" else "&") # return f"({aa} {op} {bb})" # # return [aa, op, bb] def find_xor(index): xor = xors[index][OUT] for gate in gates: if gate[OP] == "XOR" and (gate[LHS] == xor or gate[RHS] == xor): return gate return None corrected = [] for i in range(NUMBER_Z_GATES): sx, sy, sz = [f"{c}{i:02}" for c in "xyz"] gate = gates[out_to_index[sz]] if i == 0: assert gate == xors[i] elif i == NUMBER_Z_GATES - 1: pass # last gate needs special check else: fixed = False xor = xors[i] if gate[OP] != "XOR": cgate = find_xor(i) assert cgate is not None gate[OUT], cgate[OUT] = cgate[OUT], gate[OUT] corrected.append(gate[OUT]) corrected.append(cgate[OUT]) out_to_index[gate[OUT]], out_to_index[cgate[OUT]] = ( out_to_index[cgate[OUT]], out_to_index[gate[OUT]], ) fixed = True # print(f"[swap] {gate} <-> {cgate}") gate = gates[out_to_index[sz]] assert gate[OP] == "XOR" # print(gate) i_lhs, i_rhs = out_to_index[gate[LHS]], out_to_index[gate[RHS]] a, b = gates[i_lhs], gates[i_rhs] if a == xor: # print(f"[ok] {sz} ({fixed})") pass elif b == xor: # print(f"[ok] {sz} ({fixed})") gate[0], gate[2] = gate[2], gate[0] else: if a[OP] == "AND": a[OUT], xor[OUT] = xor[OUT], a[OUT] corrected.append(a[OUT]) corrected.append(xor[OUT]) # print(f"[swap] {a} <-> {xor}") out_to_index[a[OUT]], out_to_index[xor[OUT]] = ( out_to_index[xor[OUT]], out_to_index[a[OUT]], ) # print(f"[ok] {sz} (manual fix)") else: print(f"[nok] {sz} (don't know how to fix)") print(",".join(sorted(corrected)))