import { readFileSync } from 'node:fs'; const input = readFileSync('input', 'utf-8'); class Directory { constructor(parent, name) { this.parent = parent; this.name = name; this.contents = []; } getOrCreateSubdirectory(name) { let dir = this.contents.find(c => c.name === name); if (dir) { return dir; } dir = new Directory(this, name); this.contents.push(dir); return dir; } getSize() { return this.contents.reduce((size, entry) => { if (entry instanceof File) { return size + entry.size; } else { return size + entry.getSize(); } }, 0); } getRecursiveSubdirs() { const subdirs = []; for (const entry of this.contents) { if (entry instanceof Directory) { subdirs.push(entry); subdirs.push(...entry.getRecursiveSubdirs()); } } return subdirs; } } class File { constructor(parent, name, size) { this.parent = parent; this.name = name; this.size = size; } } let currentDirectory; let rootDirectory; for (const line of input.split('\n').filter(line => line)) { if (line.startsWith('$ ls')) { // ignore } else if (line.startsWith('$ cd')) { const path = line.slice(5).trim(); if (path === '..') { currentDirectory = currentDirectory.parent; } else { if (!currentDirectory) { currentDirectory = new Directory(null, path); rootDirectory = currentDirectory; } else { currentDirectory = currentDirectory.getOrCreateSubdirectory(path); } } } else { if (line.startsWith('dir')) { const path = line.slice(4).trim(); currentDirectory.getOrCreateSubdirectory(path); } else { let [size, name] = line.split(' ', 2); size = parseInt(size); const file = new File(currentDirectory, name, size); currentDirectory.contents.push(file); } } } // Sum of directories with size less than or equal to 100000 let totalSizeOfMatchingDirs = 0; for (const dir of rootDirectory.getRecursiveSubdirs()) { const size = dir.getSize(); if (size <= 100000) { totalSizeOfMatchingDirs += size; } } console.log(`Sum of directory sizes under 100000: ${totalSizeOfMatchingDirs}`); const totalDiskSpace = 70000000; const spaceNeeded = 30000000; const totalUsedSpace = rootDirectory.getSize(); const totalUnusedSpace = totalDiskSpace - totalUsedSpace; const spaceToFree = spaceNeeded - totalUnusedSpace; let sizeOfDirToDelete = rootDirectory.getSize(); for (const dir of rootDirectory.getRecursiveSubdirs()) { const size = dir.getSize(); if (size >= spaceToFree) { sizeOfDirToDelete = Math.min(sizeOfDirToDelete, size); } } console.log( `Delete directory of size ${sizeOfDirToDelete} to free ${spaceToFree}` );