137 lines
3.3 KiB
TypeScript
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))
|
|
);
|