2020aoc/day14.ts

103 lines
3.2 KiB
TypeScript

import { readFileSync } from 'fs';
const lines = readFileSync('day14/input').toString().split(/\r?\n/).filter(s => s != "");
type Mask = {
mask: string,
maskOne: bigint,
maskZero: bigint
}
type MemoryToChange = {
memPos: number,
newValue: bigint
}
type Memory = { [id: number] : bigint; }
let curMask: Mask;
const maskPrefix = "mask = ";
const maskX = /X/g;
const memRegex = new RegExp('mem\\[(?<mem>\\d+)\\] = (?<num>\\d+)');
let memoryPart1: Memory = {};
let memoryPart2: Memory = {};
const calculateMask = (line: string): Mask => {
const mask = line.substr(maskPrefix.length);
return {
mask,
maskOne: BigInt("0b" + mask.replace(maskX, '1')),
maskZero: BigInt("0b" + mask.replace(maskX, '0')),
}
}
const getMemory = (line: string): MemoryToChange => {
const match = memRegex.exec(line);
if (match == null || match.groups == undefined) {
throw new Error("regex could not find anything");
}
return {
memPos: parseInt(match.groups['mem']),
newValue: BigInt(match.groups['num'])
}
}
const changeMemoryPart1 = (memory: Memory, mask: Mask, memoryToChange: MemoryToChange) => {
memory[memoryToChange.memPos] = mask.maskZero | (mask.maskOne & memoryToChange.newValue);
}
const memoryPosCombinations = (memPosWithX: string, index: number): string[] => {
if (index > memPosWithX.length) {
return [""];
}
const partialMemPositions = memoryPosCombinations(memPosWithX, index + 1);
if (memPosWithX[index] != 'X') {
return partialMemPositions.map(partialMemPos => memPosWithX[index] + partialMemPos);
}
return partialMemPositions.map(partialMemPos => '0' + partialMemPos).concat(partialMemPositions.map(partialMemPos => '1' + partialMemPos));
}
const combineMaskAndMemPos = (memPosAsBinary: string): ((mask: string, i: number) => string) => {
return (mask, i) => {
if (mask == '0') {
return memPosAsBinary[i];
} else {
return mask
}
};
}
const parseBinaryInt = (s: string): number => parseInt(s, 2);
const calculateMemoryPositions = (mask: string, memPos: number): number[] => {
const memPosAsBinary = memPos.toString(2).padStart(mask.length, "0");
const memPosWithMask = mask.split('').map(combineMaskAndMemPos(memPosAsBinary)).join('');
return memoryPosCombinations(memPosWithMask, 0).map(parseBinaryInt);
}
const changeMemoryPart2 = (memory: Memory, mask: Mask, memoryToChange: MemoryToChange) => {
calculateMemoryPositions(mask.mask, memoryToChange.memPos).forEach(pos => memory[pos] = memoryToChange.newValue);
}
curMask = calculateMask(lines[0]);
for (const line of lines.slice(1)) {
if (line.startsWith(maskPrefix)) {
curMask = calculateMask(line);
continue;
}
const memoryToChange = getMemory(line);
changeMemoryPart1(memoryPart1, curMask, memoryToChange);
changeMemoryPart2(memoryPart2, curMask, memoryToChange);
}
const sumOfMemory1 = Object.values(memoryPart1).reduce(((previousValue, currentValue) => previousValue + currentValue), 0n);
const sumOfMemory2 = Object.values(memoryPart2).reduce(((previousValue, currentValue) => previousValue + currentValue), 0n);
console.log(sumOfMemory1);
console.log(sumOfMemory2);