From 790f3ceaec3c626335e6067e8edfa4236d805429 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Thu, 1 Dec 2022 12:33:06 -0600 Subject: [PATCH] Port common input fetcher helpers, cleanup, and add tests --- 2021/nim/.gitignore | 3 +++ 2022/deno/common.ts | 55 ++++++++++++++++++++++++++++++++++++++++ 2022/deno/day1.ts | 62 ++++++++++++++++++++++++++++++++------------- 3 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 2021/nim/.gitignore create mode 100644 2022/deno/common.ts diff --git a/2021/nim/.gitignore b/2021/nim/.gitignore new file mode 100644 index 0000000..c81f834 --- /dev/null +++ b/2021/nim/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!*.nim diff --git a/2022/deno/common.ts b/2022/deno/common.ts new file mode 100644 index 0000000..59c5e5e --- /dev/null +++ b/2022/deno/common.ts @@ -0,0 +1,55 @@ +import { copy } from "https://deno.land/std@0.167.0/streams/copy.ts"; +import * as path from "https://deno.land/std@0.167.0/path/mod.ts"; +import { readLines } from "https://deno.land/std@0.167.0/io/buffer.ts"; +import { readerFromStreamReader } from "https://deno.land/std@0.167.0/streams/reader_from_stream_reader.ts"; + +const YEAR: number = parseInt(Deno.env.get("AOC_YEAR") || "2022"); +const HOME = Deno.env.get("HOME"); +if (!HOME) throw new Error("HOME not set"); +const COOKIE_PATH = path.resolve(`${HOME}/.advent-of-code-session-cookie`); +const CACHE_DIR = path.resolve(`${HOME}/.cache/aoc${YEAR}`); + +async function loadSessionCookie() { + const td = new TextDecoder(); + const bytes = await Deno.readFile(COOKIE_PATH); + return td.decode(bytes); +} + +function inputFilePath(day: number): string { + return path.resolve(path.join(CACHE_DIR, `${day}.input`)); +} + +async function fetchAndCacheInput(day: number): Promise { + const req = new Request(`https://adventofcode.com/${YEAR}/day/${day}/input`); + req.headers.set("Cookie", await loadSessionCookie()); + const resp = await fetch(req); + const f = await Deno.open(inputFilePath(day), { write: true }); + if (!resp.body) { + throw new Error("Response had empty body"); + } + await copy(readerFromStreamReader(resp.body.getReader()), f); +} + +export async function inputLines( + day: number, + fetched = false, +): Promise> { + try { + return readLines(await Deno.open(inputFilePath(day), { read: true })); + } catch (e) { + if (!fetched) { + await fetchAndCacheInput(day); + return await inputLines(day, true); + } else { + throw e; + } + } +} + +export async function inputLinesArray(day: number) { + const lines = []; + for await (const l of await inputLines(day)) { + lines.push(l); + } + return lines; +} diff --git a/2022/deno/day1.ts b/2022/deno/day1.ts index d4d61ea..7bdee45 100644 --- a/2022/deno/day1.ts +++ b/2022/deno/day1.ts @@ -1,19 +1,47 @@ -const tDec = new TextDecoder(); -const input = tDec.decode(Deno.readFileSync("../inputs/day1.input")); +import { inputLinesArray } from "./common.ts"; -console.log( - "final", - input.split("\n\n").map((p) => { - const ns = p.split("\n").map((s) => { - const n = parseInt(s, 10); - console.log("inner", s, n); - return n; - }).filter((n) => !isNaN(n)); - if (ns.length < 1) return NaN; - const n = ns.reduce((prev, cur) => prev + cur, 0); - console.log("oter", p, n, ns); - return n; - }).filter((n) => !isNaN(n)).sort().reverse(), -); +function orderedCalories(lines: string[]) { + const calories: number[] = [0]; -console.log(71924 + 69893 + 68589); + lines.forEach((line) => { + if (line.trim() == "") { + calories.splice(0, 0, 0); + } else { + calories[0] += parseInt(line); + } + }); + calories.sort((a, b) => b - a); + return calories; +} + +const calories = orderedCalories(await inputLinesArray(1)); +console.log("Part 1:", calories[0]); +console.log("Part 2:", calories.slice(0, 3).reduce((a, b) => a + b)); + +const TEST_INPUT = `1000 +2000 +3000 + +4000 + +5000 +6000 + +7000 +8000 +9000 + +10000`.split("\n"); + +Deno.test("orderedCalories", async (t) => { + const { assertEquals } = await import( + "https://deno.land/std@0.167.0/testing/asserts.ts" + ); + + const calories = orderedCalories(TEST_INPUT); + await t.step("part 1", () => assertEquals(calories[0], 24000)); + await t.step( + "part 2", + () => assertEquals(calories.slice(0, 3).reduce((a, b) => a + b), 45000), + ); +});