ProjectsAOCBlogAbout

Day 07: No Space On Device

**
Something about the hand held device hard drive being full. Gotta figure out what to delete. Walk a directory tree and add up what's in all of it. Find the smaller directories.
Journal

This is the first one that I started to do in the new remix app I created.

Not super hard to pop in an out of directories and create an object of all the directories and the directories they contain. Then recursively populate all the sizes.

The main mistake I had was that there were directories with the same name in different paths. At first I was just keying the object on the directory name. I changed it to be keyed on the full path and it worked.

Relevant Code
// Make ano object with all the directories keyed on directory full paths
export const getDirectories = (commandInput: string) => {
const commands = commandInput.split("\n");
const directories: Record<string, Record<string, string>> = {};
// keep track of the current path to be able to push and pop directories
let currentPath: string[] = ["/"];
const handleChangeDir = (dir: string) => {
switch (dir) {
case "/":
currentPath = ["/"];
break;
case "..":
currentPath.pop();
break;
default:
currentPath.push(dir);
}
};
commands.forEach((command) => {
// If it starts with $ then it's a command
const commandMatch = command.match(/^\$ ([a-z]*) ?([a-z,A-Z,//,.]*)?/);
if (commandMatch) {
switch (commandMatch[1]) {
case "cd":
// handle change dir
handleChangeDir(commandMatch[2]);
case "ls":
// eat list
}
} else {
// otherwise it's a directory or a file
const currentDirectory = currentPath.join(",");
if (!directories[currentDirectory]) {
directories[currentDirectory] = {};
}
const [first, name] = command.split(" ");
if (first === "dir") {
// put the directory in the object
directories[currentDirectory][`${currentDirectory},${name}`] = first;
} else {
// put the file size in the object
directories[currentDirectory][name] = first;
}
}
});
return directories;
};
// recursive function to populate the sizes of all the directories (assuming no loops)
const getDirectorySize = (
directories: Record<string, Record<string, string>>,
targetDir: string
) => {
let size = 0;
const directory = directories[targetDir];
for (const key in directory) {
if (directory[key] === "dir") {
size += getDirectorySize(directories, key);
} else {
size += +directory[key];
}
}
return size;
};
export const getTargetDirectoriesSize = (
directories: Record<string, Record<string, string>>
) => {
let sum = 0;
let best = { dir: "fake", size: Infinity }; // start it off big
const avail = 70000000 - getDirectorySize(directories, "/");
const needed = 30000000 - avail;
for (const key in directories) {
const size = getDirectorySize(directories, key);
// The best is the smallest directory that's big enough to free up at least the needed space
if (size >= needed && size < best.size) {
best = { dir: key, size };
}
// if it's too big we don't care anymore, don't bother...
if (size <= 100000) {
sum += size;
}
}
return { sum, best };
};
Output

Test Directories (1ms):

  1. Part I: 95437
  2. Part II: 24933642
Real Directories (3ms):
  1. Part I: 1770595
  2. Part II: 2195372