const fs = require('fs'); const input = fs.readFileSync(__dirname + '/input.txt', 'utf8'); const [initStr, gatesStr] = input.split("\n\n"); const originalValMap: { [key: string]: number }= {}; let valMap: { [key: string]: number } = {}; const gateMap: { [key: string]: [string, string, string] } = {}; let xStr = ''; let yStr = ''; const outputWires: Array = []; initStr.split("\n").forEach((s: string) => { const [wire, val] = s.split(': '); originalValMap[wire] = parseInt(val, 2); if (wire.startsWith('x')) { xStr += val; } else { yStr += val; } }); valMap = {...originalValMap}; gatesStr.split("\n").forEach((s: string) => { const [inp, out] = s.split(' -> '); const [val1, op, val2] = inp.split(' '); gateMap[out] = [val1, op, val2]; if (out.startsWith('z')) { outputWires.push(out); } }); function getWireVal(wire: string, trace: Array = []): number { if (Object.hasOwn(valMap, wire)) { return valMap[wire]; } const [wire1, op, wire2] = gateMap[wire]; if (trace.includes(wire1) || trace.includes(wire2)) { throw Error('Cycle'); } const val = getVal(wire1, op, wire2, [...trace, wire1, wire2]); valMap[wire] = val; return val; } function getVal(wire1: string, op: string, wire2: string, trace: Array = []): number { const val1 = getWireVal(wire1, trace); const val2 = getWireVal(wire2, trace); return { AND: () => val1 & val2, OR: () => val1 | val2, XOR: () => val1 ^ val2, }[op]!(); } outputWires.sort().reverse(); function calculate() { let outputStr = ''; valMap = {...originalValMap}; outputWires.forEach((wire) => { outputStr += getWireVal(wire); }); return outputStr; } function mistakes(act: string, exp: string): number { let mistakes = 0; for (let i = 0; i < act.length; i++) { if (act[i] !== exp[i]) { mistakes++; } } return mistakes; } let fewestMistakes: number|null = null; let bestSwap: [string, string]|null = null; let swapResult: string|null = null; const wires = Object.keys(gateMap); const expected = (parseInt(xStr, 2) + parseInt(yStr, 2)).toString(2); for (let i = 0; i < wires.length; i++) { for (let j = i + 1; j < wires.length; j++) { const wireA = wires[i]; const wireB = wires[j]; const gateA = gateMap[wireA]; const gateB = gateMap[wireB]; gateMap[wireA] = gateB; gateMap[wireB] = gateA; let actual; try { actual = calculate(); } catch (e) { continue; } finally { gateMap[wireA] = gateA; gateMap[wireB] = gateB; } const mist = mistakes(actual, expected); if (!fewestMistakes || fewestMistakes > mist) { fewestMistakes = mist; bestSwap = [wireA, wireB]; swapResult = actual; } } } console.log(xStr); console.log(yStr); console.log(expected); console.log(calculate()); console.log(fewestMistakes); console.log(bestSwap); console.log(swapResult);