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