diff --git a/17/index.ts b/17/index.ts new file mode 100644 index 0000000..8c05b73 --- /dev/null +++ b/17/index.ts @@ -0,0 +1,117 @@ +import fs from "node:fs"; +import { printTime, now, toNum } from "../util"; + +const test = false; + +const data = fs.readFileSync( + test ? "./inputs/testinput" : "./inputs/input", + "utf8" +); + +let timer = now.instant(); + +let computer = data + .split("\n") + .slice(0, -1) + .reduce( + (state, line, i) => { + switch (i) { + case 0: + state.A = toNum(line.split(": ")[1]); + break; + case 1: + state.B = toNum(line.split(": ")[1]); + break; + case 2: + state.C = toNum(line.split(": ")[1]); + break; + case 3: + break; + case 4: + state.Program = line.split(": ")[1].split(",").map(toNum); + } + return state; + }, + { A: 0, B: 0, C: 0, Program: [], Output: [] } as { + A: number; + B: number; + C: number; + Program: number[]; + Output: number[]; + } + ); + +const comboOperand = (computer, instructionPointer: number) => { + switch (computer.Program[instructionPointer + 1]) { + case 0: + case 1: + case 2: + case 3: + return computer.Program[instructionPointer + 1]; + case 4: + return computer.A; + case 5: + return computer.B; + case 6: + return computer.C; + case 7: + throw "invalid!"; + } +}; + +let instructionPointer = 0; +while (instructionPointer < computer.Program.length) { + let instruction = computer.Program[instructionPointer]; + switch (instruction) { + case 0: // adv: A/(2^combo-operand) => A + computer.A = Math.trunc( + computer.A / 2 ** comboOperand(computer, instructionPointer) + ); + instructionPointer += 2; + break; + case 1: // bxl: XOR(B, literal=operand) => B + computer.B = computer.B ^ computer.Program[instructionPointer + 1]; + instructionPointer += 2; + break; + case 2: // bst: combo-operand % 8 => B + computer.B = comboOperand(computer, instructionPointer) % 8; + instructionPointer += 2; + break; + case 3: // jnz: jump to literal operand if non-zero register A + if (computer.A !== 0) { + instructionPointer = computer.Program[instructionPointer + 1]; + } else { + instructionPointer += 2; + } + break; + case 4: // bxc: XOR(B, C) => B (consumes and ignores operand) + computer.B = computer.B ^ computer.C; + instructionPointer += 2; + break; + case 5: // out: combo-operand => Output + computer.Output.push(comboOperand(computer, instructionPointer) % 8); + instructionPointer += 2; + break; + case 6: // bdv: A/(2^combo-operand) => B + computer.B = Math.trunc( + computer.A / 2 ** comboOperand(computer, instructionPointer) + ); + instructionPointer += 2; + break; + case 7: // cdv: A/(2^combo-operand) => C + computer.C = Math.trunc( + computer.A / 2 ** comboOperand(computer, instructionPointer) + ); + instructionPointer += 2; + break; + } +} + +console.log( + "part one:", + computer.Output.join(","), + printTime(now.instant().since(timer)) +); + +// timer = now.instant(); +// console.log("part two:", computer, printTime(now.instant().since(timer)));