From fdc626005595f9c2a1e8a0fb1393dca54a8002f9 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 24 Dec 2024 10:13:53 +0000 Subject: [PATCH] Day 24 Part 1 --- 2024/24/index.ts | 54 ++++++++++++++++++++ 2024/24/index2.ts | 123 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 2024/24/index.ts create mode 100644 2024/24/index2.ts diff --git a/2024/24/index.ts b/2024/24/index.ts new file mode 100644 index 0000000..cb7782c --- /dev/null +++ b/2024/24/index.ts @@ -0,0 +1,54 @@ +const fs = require('fs'); + +const input = fs.readFileSync(__dirname + '/input.txt', 'utf8'); + +const [initStr, gatesStr] = input.split("\n\n"); + +const valMap: { [key: string]: number }= {}; +const gateMap: { [key: string]: [string, string, string] } = {}; + +const outputWires: Array = []; + +initStr.split("\n").forEach((s: string) => { + const [wire, val] = s.split(': '); + valMap[wire] = parseInt(val, 2); +}); + +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): number { + if (Object.hasOwn(valMap, wire)) { + return valMap[wire]; + } + const val = getVal(...gateMap[wire]) + valMap[wire] = val; + return val; +} + +function getVal(wire1: string, op: string, wire2: string): number { + const val1 = getWireVal(wire1); + const val2 = getWireVal(wire2); + + return { + AND: () => val1 & val2, + OR: () => val1 | val2, + XOR: () => val1 ^ val2, + }[op]!(); +} + +outputWires.sort().reverse(); + +let outputStr = ''; + +outputWires.forEach((wire) => { + outputStr += getWireVal(wire); +}); + +console.log(outputStr, parseInt(outputStr, 2)); diff --git a/2024/24/index2.ts b/2024/24/index2.ts new file mode 100644 index 0000000..806e364 --- /dev/null +++ b/2024/24/index2.ts @@ -0,0 +1,123 @@ +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);