Files
advent-of-code-2022/2022/07/solution.ts
2022-12-12 16:50:53 +01:00

192 lines
5.2 KiB
TypeScript

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