Solve 2024 day 24
This commit is contained in:
parent
8cc199105c
commit
2ee16eb1ba
143
2024/d24.py
Normal file
143
2024/d24.py
Normal 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)))
|
@ -314,5 +314,6 @@ and focus. Of course, learning more algorithms and techniques helps.
|
|||||||
- Day 21: `00:48:40 215 0 - - -`
|
- Day 21: `00:48:40 215 0 - - -`
|
||||||
- Day 22: `00:13:04 1930 0 00:28:29 739 0`
|
- Day 22: `00:13:04 1930 0 00:28:29 739 0`
|
||||||
- Day 23: ` >24h 20096 0 >24h 17620 0`
|
- Day 23: ` >24h 20096 0 >24h 17620 0`
|
||||||
- Day 24:
|
- Day 24: `15:57:01 17307 0 >24h 11326 0`
|
||||||
- Day 25:
|
- Day 25: `10:41:54 14140 0 - - -`
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user