Solve 2024-17
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import { unsignedXOR } from '../../utils/numbers.ts';
|
||||
|
||||
const Instructions = {
|
||||
adv: 0,
|
||||
bxl: 1,
|
||||
bst: 2,
|
||||
jnz: 3,
|
||||
bxc: 4,
|
||||
out: 5,
|
||||
bdv: 6,
|
||||
cdv: 7
|
||||
} as const;
|
||||
|
||||
type Instruction = (typeof Instructions)[keyof typeof Instructions];
|
||||
|
||||
function runCode(
|
||||
instructions: Instruction[],
|
||||
regA: number,
|
||||
regB: number,
|
||||
regC: number
|
||||
) {
|
||||
let instructionPointer = 0;
|
||||
const output: number[] = [];
|
||||
|
||||
while (instructionPointer < instructions.length) {
|
||||
let instruction = instructions[instructionPointer];
|
||||
let operand = instructions[instructionPointer + 1];
|
||||
let comboOperand: number = operand;
|
||||
if (operand === 4) {
|
||||
comboOperand = regA;
|
||||
} else if (operand === 5) {
|
||||
comboOperand = regB;
|
||||
} else if (operand === 6) {
|
||||
comboOperand = regC;
|
||||
}
|
||||
|
||||
let jumped = false;
|
||||
// console.log(regA, regB, regC, instruction, operand);
|
||||
switch (instruction) {
|
||||
case Instructions.adv:
|
||||
regA = Math.floor(regA / Math.pow(2, comboOperand));
|
||||
break;
|
||||
case Instructions.bdv:
|
||||
regB = Math.floor(regA / Math.pow(2, comboOperand));
|
||||
break;
|
||||
case Instructions.cdv:
|
||||
regC = Math.floor(regA / Math.pow(2, comboOperand));
|
||||
break;
|
||||
case Instructions.bxl:
|
||||
regB = unsignedXOR(regB, operand);
|
||||
break;
|
||||
case Instructions.bst:
|
||||
regB = comboOperand % 8;
|
||||
break;
|
||||
case Instructions.jnz:
|
||||
if (regA !== 0) {
|
||||
instructionPointer = operand;
|
||||
jumped = true;
|
||||
}
|
||||
break;
|
||||
case Instructions.bxc:
|
||||
regB = unsignedXOR(regB, regC);
|
||||
break;
|
||||
case Instructions.out:
|
||||
output.push(comboOperand % 8);
|
||||
break;
|
||||
}
|
||||
if (!jumped) {
|
||||
instructionPointer += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return output.join(',');
|
||||
}
|
||||
|
||||
export function solveFirst(input: string): string {
|
||||
const match = input.match(
|
||||
/^Register A: (\d*)\nRegister B: (\d*)\nRegister C: (\d*)\n\nProgram: ([\d,]*)$/m
|
||||
);
|
||||
if (!match) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const instructions = match[4].split(',').map(Number) as Instruction[];
|
||||
return runCode(
|
||||
instructions,
|
||||
Number(match[1]),
|
||||
Number(match[2]),
|
||||
Number(match[3])
|
||||
);
|
||||
}
|
||||
|
||||
export function solveSecond(input: string): number {
|
||||
const match = input.match(
|
||||
/^Register A: (\d*)\nRegister B: (\d*)\nRegister C: (\d*)\n\nProgram: ([\d,]*)$/m
|
||||
);
|
||||
if (!match) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const instructions = match[4].split(',').map(Number) as Instruction[];
|
||||
|
||||
const regB = Number(match[2]);
|
||||
const regC = Number(match[3]);
|
||||
|
||||
const possible: { result: string; length: number }[] = [];
|
||||
possible.push({ result: '', length: 0 });
|
||||
while (possible.length) {
|
||||
const { result, length } = possible.shift()!;
|
||||
if (length === instructions.length) {
|
||||
return parseInt(result, 2);
|
||||
}
|
||||
const from = parseInt(`${result}000`, 2);
|
||||
const to = parseInt(`${result}111`, 2);
|
||||
|
||||
const expect = instructions.slice(-(length + 1)).join(',');
|
||||
for (let regA = from; regA <= to; regA++) {
|
||||
const r = runCode(instructions, regA, regB, regC);
|
||||
if (r === expect) {
|
||||
possible.push({ result: regA.toString(2), length: length + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user