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 pathsexport 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 directorieslet 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 commandconst commandMatch = command.match(/^\$ ([a-z]*) ?([a-z,A-Z,//,.]*)?/);if (commandMatch) {switch (commandMatch[1]) {case "cd":// handle change dirhandleChangeDir(commandMatch[2]);case "ls":// eat list}} else {// otherwise it's a directory or a fileconst currentDirectory = currentPath.join(",");if (!directories[currentDirectory]) {directories[currentDirectory] = {};}const [first, name] = command.split(" ");if (first === "dir") {// put the directory in the objectdirectories[currentDirectory][`${currentDirectory},${name}`] = first;} else {// put the file size in the objectdirectories[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 bigconst 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 spaceif (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):
- Part I: 95437
- Part II: 24933642
Real Directories (3ms):
- Part I: 1770595
- Part II: 2195372