summaryrefslogtreecommitdiff
path: root/day-7/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'day-7/index.ts')
-rw-r--r--day-7/index.ts126
1 files changed, 126 insertions, 0 deletions
diff --git a/day-7/index.ts b/day-7/index.ts
new file mode 100644
index 0000000..689e647
--- /dev/null
+++ b/day-7/index.ts
@@ -0,0 +1,126 @@
+import fs from "fs";
+
+const file = fs.readFileSync("./input.txt").toString();
+
+const lines = file.split("\n").filter((x) => x.length);
+
+// File or Directory
+interface Item {
+ type: "dir" | "file";
+ name: string;
+ size: number;
+}
+
+interface CommandWithOutput {
+ command: string;
+ outputs: Item[];
+}
+
+interface CommandWithDir extends CommandWithOutput {
+ directory: string[];
+}
+
+function isCommandString(s: string) {
+ return s.startsWith("$");
+}
+
+function parseLines(lines: string[]): CommandWithOutput[] {
+ return lines.reduce((acc, current, index) => {
+ if (isCommandString(current)) {
+ const nextCommandIndex =
+ lines.slice(index + 1).findIndex(isCommandString) + index + 1;
+
+ const smartIndex =
+ nextCommandIndex === index ? lines.length : nextCommandIndex;
+ const outputs = lines.slice(index + 1, smartIndex).map((line) => {
+ const dirMatch = line.match(/dir (.*)/);
+ const fileMatch = line.match(/(.*) (.*)/);
+
+ if (dirMatch && dirMatch[1])
+ return {
+ type: "dir",
+ size: 0,
+ name: dirMatch[1],
+ } satisfies Item;
+ if (fileMatch)
+ return {
+ type: "file",
+ size: Number(fileMatch[1]),
+ name: fileMatch[2],
+ } satisfies Item;
+ throw new Error("Unhandled");
+ });
+ acc.push({ outputs, command: current });
+ }
+ return acc;
+ }, [] as CommandWithOutput[]);
+}
+
+function computeDirectories(commands: CommandWithOutput[]): CommandWithDir[] {
+ return commands.reduce((acc, current) => {
+ const previousDir = acc[acc.length - 1]?.directory;
+
+ const match = current.command.match(/\$ cd (.*)/);
+ const directory = match
+ ? previousDir
+ ? match[1] !== ".."
+ ? [...previousDir, match[1]]
+ : [...previousDir.slice(0, -1)]
+ : [match[1]]
+ : [...previousDir];
+
+ acc.push({ ...current, directory });
+ return acc;
+ }, [] as CommandWithDir[]);
+}
+
+const parsed = parseLines(lines);
+const withDirs = computeDirectories(parsed);
+const lsOutputs = withDirs.filter((cmd) => cmd.command === "$ ls");
+
+// DIRTY CODE STARTS HERE
+function computeDirSize(
+ cmd: CommandWithDir & { totalSize: number | undefined },
+) {
+ if (cmd.totalSize !== undefined) return;
+ cmd.outputs
+ .filter((f) => f.type === "dir")
+ .forEach((dir) => {
+ const path = [...cmd.directory, dir.name];
+ const dirNode = data.find(
+ (datum) => JSON.stringify(datum.directory) === JSON.stringify(path),
+ );
+
+ if (!dirNode) throw new Error(`Unknown size ${dir.name}`);
+ if (dirNode.totalSize === undefined) {
+ computeDirSize(dirNode);
+ }
+ if (dirNode.totalSize !== undefined) {
+ dir.size = dirNode.totalSize;
+ } else {
+ throw new Error(
+ `${dir.name}, ${JSON.stringify(path)}, ${JSON.stringify(dirNode)}`,
+ );
+ }
+ });
+
+ const totalSize = cmd.outputs.reduce((sum, f) => sum + f.size, 0);
+
+ cmd.totalSize = totalSize;
+ // console.log("Setting size ", totalSize, " to dir", cmd.directory);
+}
+
+const data = lsOutputs.map((o) => ({
+ ...o,
+ totalSize: undefined as undefined | number,
+}));
+
+data.forEach(computeDirSize);
+console.log(data);
+
+const sum = data
+ .filter((d) => d.totalSize)
+ .filter((datum) => (datum?.totalSize || 0) <= 100_000)
+ .reduce((acc, d) => acc + (d?.totalSize || 0), 0);
+
+console.log(sum);