Solve 2024 day 24

This commit is contained in:
felixm 2024-12-25 12:14:04 -05:00
parent 8cc199105c
commit 2ee16eb1ba
2 changed files with 146 additions and 2 deletions

143
2024/d24.py Normal file
View File

@ -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)))

View File

@ -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 - - -`