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)));