diff --git a/2022/07/part1.js b/2022/07/part1.js new file mode 100644 index 0000000..a855124 --- /dev/null +++ b/2022/07/part1.js @@ -0,0 +1,67 @@ +import * as R from "remeda"; +import { readFile } from "../05/part1.js"; +import path from "path"; + +const readInput = (...args) => + readFile(...args) + .split("\n") + .filter((x) => x); + +export const puzzleInput = readInput(import.meta.url, "input"); +export const sample = readInput(import.meta.url, "sample"); + +export function parseInput(lines) { + lines = [...lines]; + + let currentDir = "/"; + + const data = {}; + + while (lines.length > 0) { + const line = lines.shift(); + + let match = line.match(/\$ cd (.*)/); + if (match) { + currentDir = match[1].startsWith("/") + ? match[1] + : path.join(currentDir, match[1]); + if (!data[currentDir]) data[currentDir] = 0; + continue; + } + + if (/^\d+/.test(line)) { + const [size] = line.match(/\d+/); + data[currentDir] += parseInt(size); + } + } + + return data; +} + +export function cumulative(individual) { + const isIn = (k, targetKey) => { + const result = + k === targetKey || + k.startsWith(targetKey.endsWith("/") ? targetKey : targetKey + "/"); + return result; + }; + + return R.pipe( + individual, + R.mapValues((v, targetKey) => { + const sum = R.sumBy( + Object.values(R.pickBy(individual, (v, k) => isIn(k, targetKey))), + R.identity + ); + return sum; + }) + ); +} + +export default R.createPipe( + parseInput, + cumulative, + R.pickBy((v) => v <= 100000), + R.values, + R.sumBy(R.identity) +); diff --git a/2022/07/part2.js b/2022/07/part2.js new file mode 100644 index 0000000..3d8be98 --- /dev/null +++ b/2022/07/part2.js @@ -0,0 +1,20 @@ +import * as R from "remeda"; + +import { cumulative, parseInput } from "./part1.js"; + +export default (lines) => { + let cumu = R.pipe(lines, parseInput, cumulative); + + console.log(cumu); + + const spaceNeeded = 30000000 - 70000000 + cumu["/"]; + + cumu = R.pickBy(cumu, (v) => v >= spaceNeeded); + + return R.pipe( + R.keys(cumu), + R.sortBy((k) => cumu[k]), + R.first, + (k) => cumu[k] + ); +}; diff --git a/2022/07/sample b/2022/07/sample new file mode 100644 index 0000000..09a921e --- /dev/null +++ b/2022/07/sample @@ -0,0 +1,23 @@ +$ cd / +$ ls +dir a +14848514 b.txt +8504156 c.dat +dir d +$ cd a +$ ls +dir e +29116 f +2557 g +62596 h.lst +$ cd e +$ ls +584 i +$ cd .. +$ cd .. +$ cd d +$ ls +4060174 j +8033020 d.log +5626152 d.ext +7214296 k diff --git a/2022/07/test.js b/2022/07/test.js new file mode 100644 index 0000000..6e59ec7 --- /dev/null +++ b/2022/07/test.js @@ -0,0 +1,38 @@ +import { test, expect, describe } from "vitest"; + +import { expectSolution } from "../01/main.js"; +import part1, { puzzleInput, sample, parseInput, cumulative } from "./part1.js"; +import part2 from "./part2.js"; + +describe("part 1", () => { + const expected = { "/": 23352670, "/a": 94269, "/a/e": 584, "/d": 24933642 }; + + test("parseInput", () => { + const data = parseInput(sample); + + expect(data).toEqual(expected); + }); + + test("cumulative", () => { + expect(cumulative(expected)).toEqual({ + "/": 48381165, + "/a": 94853, + "/a/e": 584, + "/d": 24933642, + }); + }); + + test("solution", () => { + expectSolution(part1(puzzleInput)).toEqual(1350966); + }); +}); + +describe("part 2", () => { + test("sample", () => { + expect(part2(sample)).toEqual(24933642); + }); + test("solution", () => { + expectSolution(part2(puzzleInput)).toBeLessThan(46647330); + expectSolution(part2(puzzleInput)).toEqual(6296435); + }); +});