2022 - Day 7
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
const sample = await Deno.readTextFile("sample.txt");
|
||||
const input = await Deno.readTextFile("input.txt");
|
||||
|
||||
/**** TYPES *********************************/
|
||||
|
||||
interface LSCommandInfo {
|
||||
type: "command";
|
||||
command: "ls";
|
||||
}
|
||||
interface CDCommandInfo {
|
||||
type: "command";
|
||||
command: "cd";
|
||||
name: string;
|
||||
}
|
||||
interface FileInfo {
|
||||
type: "file";
|
||||
size: number;
|
||||
name: string;
|
||||
}
|
||||
interface DirectoryInfo {
|
||||
type: "dir";
|
||||
name: string;
|
||||
}
|
||||
type InfoItem = LSCommandInfo | CDCommandInfo | FileInfo | DirectoryInfo;
|
||||
|
||||
class Directory {
|
||||
public parent: Directory | undefined;
|
||||
public name: string;
|
||||
public size = 0;
|
||||
public files: string[] = [];
|
||||
public dirs: Directory[] = [];
|
||||
|
||||
constructor({ name, parent }: { name: string; parent?: Directory }) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
getDir(name: string): Directory | undefined {
|
||||
return this.dirs.find((dir) => dir.name === name);
|
||||
}
|
||||
|
||||
hasDir(name: string): boolean {
|
||||
return this.dirs.some((dir) => dir.name === name);
|
||||
}
|
||||
|
||||
hasFile(name: string): boolean {
|
||||
return this.files.some((file) => file === name);
|
||||
}
|
||||
|
||||
addDir(name: string): Directory {
|
||||
if (this.hasDir(name)) {
|
||||
return this.getDir(name)!;
|
||||
}
|
||||
const newDir = new Directory({ parent: this, name });
|
||||
this.dirs.push(newDir);
|
||||
return newDir;
|
||||
}
|
||||
|
||||
get totalSize(): number {
|
||||
return (
|
||||
this.size + this.dirs.reduce((total, dir) => total + dir.totalSize, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**** FUNCTIONS *****************************/
|
||||
|
||||
const parseData = (data: string): InfoItem[] => {
|
||||
return data
|
||||
.split("\n")
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
const parts = line.split(" ");
|
||||
if (parts[0] === "$") {
|
||||
return {
|
||||
type: "command",
|
||||
command: parts[1] === "ls" ? "ls" : "cd",
|
||||
name: parts.slice(2).join(" "),
|
||||
};
|
||||
} else if (!isNaN(parseFloat(parts[0]))) {
|
||||
return { type: "file", size: parseFloat(parts[0]), name: parts[1] };
|
||||
} else {
|
||||
return { type: "dir", name: parts.slice(1).join(" ") };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flatten = (dir: Directory): Directory[] => [
|
||||
dir,
|
||||
...dir.dirs.flatMap((dir) => flatten(dir)),
|
||||
];
|
||||
|
||||
const printTree = (rootDir: Directory): void => {
|
||||
const printDirecory = (level: number, dir: Directory) => {
|
||||
console.log(
|
||||
`${"".padStart(level, " ")}${dir.name} - ${dir.size} - ${dir.totalSize}`
|
||||
);
|
||||
dir.dirs.forEach((dir) => printDirecory(level + 1, dir));
|
||||
};
|
||||
|
||||
printDirecory(0, rootDir);
|
||||
};
|
||||
|
||||
/**** PART 1 ********************************/
|
||||
|
||||
const solvePart1 = (data: string): number => {
|
||||
let rootDir: Directory | undefined = undefined;
|
||||
let currentDir: Directory | undefined = undefined;
|
||||
|
||||
parseData(data).forEach((infoItem) => {
|
||||
if (infoItem.type === "command" && infoItem.command === "cd") {
|
||||
if (infoItem.name === "/") {
|
||||
currentDir = rootDir = new Directory({ name: "/" });
|
||||
} else if (infoItem.name === "..") {
|
||||
if (!currentDir?.parent) {
|
||||
throw new Error("There is no parent directory for " + infoItem.name);
|
||||
}
|
||||
currentDir = currentDir?.parent;
|
||||
} else {
|
||||
currentDir = currentDir?.addDir(infoItem.name);
|
||||
}
|
||||
} else if (infoItem.type === "file") {
|
||||
if (!currentDir) {
|
||||
throw new Error("There is no directory to add files to");
|
||||
}
|
||||
if (currentDir.hasFile(infoItem.name)) {
|
||||
return;
|
||||
}
|
||||
currentDir.files.push(infoItem.name);
|
||||
currentDir.size += infoItem.size;
|
||||
} else if (infoItem.type === "dir") {
|
||||
currentDir?.addDir(infoItem.name);
|
||||
}
|
||||
});
|
||||
if (rootDir === undefined) {
|
||||
return -1;
|
||||
}
|
||||
return flatten(rootDir)
|
||||
.filter((dir) => dir.totalSize < 100000)
|
||||
.map((dir) => dir.totalSize)
|
||||
.reduce((sum, value) => sum + value, 0);
|
||||
};
|
||||
|
||||
console.log("Sample:", solvePart1(sample)); // 95437
|
||||
console.log("Input", solvePart1(input)); //1611443
|
||||
|
||||
/**** PART 2 ********************************/
|
||||
|
||||
const solvePart2 = (data: string): number => {
|
||||
let rootDir: Directory | undefined = undefined;
|
||||
let currentDir: Directory | undefined = undefined;
|
||||
|
||||
parseData(data).forEach((infoItem) => {
|
||||
if (infoItem.type === "command" && infoItem.command === "cd") {
|
||||
if (infoItem.name === "/") {
|
||||
currentDir = rootDir = new Directory({ name: "/" });
|
||||
} else if (infoItem.name === "..") {
|
||||
if (!currentDir?.parent) {
|
||||
throw new Error("There is no parent directory for " + infoItem.name);
|
||||
}
|
||||
currentDir = currentDir?.parent;
|
||||
} else {
|
||||
currentDir = currentDir?.addDir(infoItem.name);
|
||||
}
|
||||
} else if (infoItem.type === "file") {
|
||||
if (!currentDir) {
|
||||
throw new Error("There is no directory to add files to");
|
||||
}
|
||||
if (currentDir.hasFile(infoItem.name)) {
|
||||
return;
|
||||
}
|
||||
currentDir.files.push(infoItem.name);
|
||||
currentDir.size += infoItem.size;
|
||||
} else if (infoItem.type === "dir") {
|
||||
currentDir?.addDir(infoItem.name);
|
||||
}
|
||||
});
|
||||
if (rootDir === undefined) {
|
||||
return -1;
|
||||
}
|
||||
return (
|
||||
flatten(rootDir)
|
||||
.filter((dir) => dir.totalSize >= 2080344)
|
||||
.map((dir) => [dir.name, dir.totalSize] as [string, number])
|
||||
.sort(([, a], [, b]) => a - b)
|
||||
.shift()?.[1] || -1
|
||||
);
|
||||
};
|
||||
|
||||
console.log("Sample:", solvePart2(sample)); // 24933642
|
||||
console.log("Input", solvePart2(input)); //2086088
|
||||
Reference in New Issue
Block a user