AdventOfCode2024/09/index.ts
2024-12-15 22:38:00 -05:00

137 lines
3.3 KiB
TypeScript

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 sparceArray = data
.split("\n")
.slice(0, -1)[0]
.split("")
.map(toNum)
.reduce((disk, curr, index) => {
const fill = index % 2 === 0 ? index / 2 : -1; // -1 represents free space
return [...disk, ...Array.from({ length: curr }, () => fill)];
}, [] as Array<number>);
let rightCursor = sparceArray.length - 1;
let leftCursor = 0;
while (leftCursor < rightCursor) {
if (sparceArray[leftCursor] === -1) {
while (sparceArray[rightCursor] === -1) {
rightCursor--;
}
if (leftCursor > rightCursor) {
// don't let them overrun each other
break;
}
sparceArray[leftCursor] = sparceArray[rightCursor];
sparceArray[rightCursor] = -1;
}
leftCursor++;
}
console.log(
"part one:",
sparceArray.reduce((checksum, curr, i) => {
if (curr !== -1) {
return checksum + curr * i;
}
return checksum;
}, 0),
printTime(now.instant().since(timer))
);
timer = now.instant();
let spaces: Record<string, number[]> = {
1: [],
2: [],
3: [],
4: [],
5: [],
6: [],
7: [],
8: [],
9: [],
};
sparceArray = data
.split("\n")
.slice(0, -1)[0]
.split("")
.map(toNum)
.reduce((disk, curr, index) => {
const fill = index % 2 === 0 ? index / 2 : -1; // -1 represents free space
if (fill === -1 && curr !== 0) {
// memoize where all the gaps are, and their sizes
spaces[curr].push(disk.length);
}
return [...disk, ...Array.from({ length: curr }, () => fill)];
}, [] as Array<number>);
rightCursor = sparceArray.length - 1;
while (rightCursor > 0) {
if (sparceArray[rightCursor] === -1) {
rightCursor--;
continue;
}
let currentFileToMove = sparceArray[rightCursor];
let endOfFile = rightCursor;
while (sparceArray[rightCursor - 1] === currentFileToMove) {
rightCursor--;
}
let fileSize = endOfFile - rightCursor + 1;
// find a slot, if it exists
let target = Object.entries(spaces).reduce(
(target, [size, spaceList]) => {
if (toNum(size) >= fileSize) {
if (spaceList[0] < target.index) {
return { index: spaceList[0], size };
}
}
return target;
},
{ index: Infinity, size: "" }
);
if (target.index < Infinity && target.index < rightCursor) {
// slot exists; move the file, update the array, and update the space lists
// but only if the new location is actually to the right of our cursor
sparceArray.splice(
target.index,
fileSize,
...sparceArray.slice(rightCursor, rightCursor + fileSize)
);
sparceArray.splice(
rightCursor,
fileSize,
...Array.from({ length: fileSize }, () => -1)
);
spaces[target.size].shift();
if (toNum(target.size) - fileSize > 0) {
let newGap = (toNum(target.size) - fileSize).toString();
spaces[newGap] = [...spaces[newGap], target.index + fileSize].sort(
(a, b) => (a > b ? 1 : -1)
);
}
}
rightCursor--;
}
console.log(
"part two:",
sparceArray.reduce((checksum, curr, i) => {
if (curr !== -1) {
return checksum + curr * i;
}
return checksum;
}, 0),
printTime(now.instant().since(timer))
);