import Foundation typealias Op = (Bool, Bool) -> Bool typealias Gate = (String, Op, String, String) struct Circuit : CustomStringConvertible { let gates: [Gate] var nodes: [String: Bool] var pendingEndNodes: Set var description: String { nodes.map { "\($0): \($1 ? 1 : 0)" }.sorted().joined(separator: "\n") + "\n\(pendingEndNodes)" } func value(of prefix: String) -> Int? { if pendingEndNodes.count > 0 { return nil } return nodes.keys.filter { $0.starts(with: prefix) } .sorted().reversed().reduce(0) { $0 * 2 + (nodes[$1]! ? 1 : 0) } } mutating func run(gate: Gate) { let (in1, op, in2, out) = gate if let v1 = nodes[in1], let v2 = nodes[in2] { nodes[out] = op(v1, v2) pendingEndNodes.remove(out) } } mutating func run() { gates.forEach { run(gate: $0) } } } func readInput(_ filePath: String) throws -> Circuit { let content = try String(contentsOfFile: filePath, encoding: .ascii) let gateRe = try Regex(#"([a-z0-9]+) (AND|OR|XOR) ([a-z0-9]+) -> ([a-z0-9]+)"#) let opMap: [String: Op] = [ "AND": { $0 && $1 }, "OR": { $0 || $1 }, "XOR": { $0 != $1 } ] var gates: [Gate] = [] var endNodes: Set = [] for line in content.split(separator: "\n") { if let m = line.wholeMatch(of: gateRe) { let in1 = String(m.output[1].substring!) let op = opMap[String(m.output[2].substring!)]! let in2 = String(m.output[3].substring!) let out = String(m.output[4].substring!) gates.append((in1, op, in2, out)) if out.starts(with: "z") { endNodes.insert(out) } } } return Circuit(gates: gates, nodes: [:], pendingEndNodes: endNodes) } extension Int { func toNodes(_ prefix: String) -> [String: Bool] { var nodes: [String: Bool] = [:] for i in (0..<45) { nodes[prefix + String(format: "%02d", i)] = ((self >> i) & 1) == 1 } return nodes } } var circuit = try readInput(CommandLine.arguments[1]) // generate random x y to try let x = Int.random(in: 0..<(1<<45)) let y = Int.random(in: 0..<(1<<45)) circuit.nodes.merge(x.toNodes("x")) { l, r in l } circuit.nodes.merge(y.toNodes("y")) { l, r in l } // just print out the wrong bits for manual debugging. See input.dot // print(circuit) while true { if let z = circuit.value(of: "z") { print("x: " + String(x, radix: 2).reversed()) print("y: " + String(y, radix: 2).reversed()) let zStr = String(z, radix: 2).reversed() let pStr = String(x+y, radix: 2).reversed() let zHighlight = zip(zStr, pStr).map { dz, dp -> String in dz == dp ? String(dz) : "\u{001B}[41m\(dz)\u{001B}[0m" } print("z: " + zHighlight.joined()) print("\u{001B}[4m!: \(String(pStr))\u{001B}[0m") print(" \((0.. fkb and z31 <-> rdn