import graphviz import re def solve(data): values, wires = data.split("\n\n") values = dict([tuple(c.strip().split(": ")) for c in values.splitlines()]) wires = [w.split() for w in wires.splitlines()] Q = [*wires] while Q: a, o, b, _, c = Q.pop(0) if a not in values or b not in values: Q.append((a, o, b, "_", c)) continue a, b = int(values[a]), int(values[b]) match o: case "AND": values[c] = int(a + b == 2) case "XOR": values[c] = int(a + b == 1) case "OR": values[c] = int(a + b > 0) p1 = int( "".join( [ str(v) for k, v in sorted(values.items(), key=lambda x: x[0], reverse=True) if k.startswith("z") ] ), 2, ) # render_graph(wires) wrong_xors_inputs = r"[^y|x]\S{2}+ XOR [^x|y]\S{2}+ -> ([^z]\S{2})" wrong_z_outputs = r"\s(?:OR|AND) .+ -> (z\d{2})" found_manually = ["jqf", "skh"] p2 = ",".join( sorted( [seq for seq in re.findall(wrong_z_outputs, data) if not seq.endswith("45")] + list(re.findall(wrong_xors_inputs, data)) + found_manually ) ) return p1, p2 def render_graph(wires): dot = graphviz.Digraph(comment="The Round Table") for a, o, b, _, c in wires: ol = f"{a}{b}{o}{c}" dot.node(a) dot.node(b) dot.node(c) dot.node(ol, label=o, shape="diamond") dot.edge(a, ol) dot.edge(b, ol) dot.edge(ol, c) dot.render("2024.24.p2.gv").replace("\\", "/") if __name__ == "__main__": with open("./input/24.txt", "r") as f: inp = f.read().strip() p1, p2 = solve(inp) print(p1) print(p2)