Files
AoC/2024/24/index2.ts
2024-12-24 10:13:53 +00:00

124 lines
3.1 KiB
TypeScript

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<string> = [];
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<string> = []): 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<string> = []): 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);