Advent-of-Code-2022/7/solution.mjs
2022-12-06 22:50:41 -07:00

121 lines
2.7 KiB
JavaScript

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}`
);