From 2ee16eb1ba4dfd71576f19e71b248e34e31f646d Mon Sep 17 00:00:00 2001 From: felixm Date: Wed, 25 Dec 2024 12:14:04 -0500 Subject: [PATCH] Solve 2024 day 24 --- 2024/d24.py | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 5 +- 2 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 2024/d24.py diff --git a/2024/d24.py b/2024/d24.py new file mode 100644 index 0000000..1126738 --- /dev/null +++ b/2024/d24.py @@ -0,0 +1,143 @@ +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))) diff --git a/README.md b/README.md index 2280fd9..f63187d 100644 --- a/README.md +++ b/README.md @@ -314,5 +314,6 @@ and focus. Of course, learning more algorithms and techniques helps. - Day 21: `00:48:40 215 0 - - -` - Day 22: `00:13:04 1930 0 00:28:29 739 0` - Day 23: ` >24h 20096 0 >24h 17620 0` -- Day 24: -- Day 25: +- Day 24: `15:57:01 17307 0 >24h 11326 0` +- Day 25: `10:41:54 14140 0 - - -` +