From ecbedd342861408d3a38abd441d6fa3d5a392e29 Mon Sep 17 00:00:00 2001 From: Andres Date: Sun, 8 Dec 2024 13:11:30 +0100 Subject: [PATCH] 2024 day 8 --- 2024/day-8/day8.test.ts | 40 ++++++++ 2024/day-8/day8.ts | 186 ++++++++++++++++++++++++++++++++++++ 2024/day-8/input.txt | 50 ++++++++++ 2024/day-8/test-input-2.txt | 12 +++ 2024/day-8/test-input.txt | 12 +++ package.json | 3 + scripts/prepare.ts | 74 ++++++++++++++ 7 files changed, 377 insertions(+) create mode 100644 2024/day-8/day8.test.ts create mode 100644 2024/day-8/day8.ts create mode 100644 2024/day-8/input.txt create mode 100644 2024/day-8/test-input-2.txt create mode 100644 2024/day-8/test-input.txt create mode 100644 scripts/prepare.ts diff --git a/2024/day-8/day8.test.ts b/2024/day-8/day8.test.ts new file mode 100644 index 0000000..603413d --- /dev/null +++ b/2024/day-8/day8.test.ts @@ -0,0 +1,40 @@ +import { expect, test } from "bun:test"; +import * as path from "node:path"; +import { part1, part2 } from "./day8.ts"; + +test("day 8, part 1", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text(); + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text(); + + console.log("\n\n"); + + const testResult = part1(testInput); + console.log("Test data:", testResult); + expect(testResult).toEqual(14); + + const finalResult = part1(input); + console.log("Full data:", finalResult); + expect(finalResult).toEqual(332); + + console.log("\n\n"); +}); + +test("day 8, part 2", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text(); + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text(); + + const testResult = part2(testInput); + console.log("\n\n"); + console.log("Test data:", testResult); + expect(testResult).toEqual(34); + + const finalResult = part2(input); + console.log("Full data:", finalResult); + expect(finalResult).toEqual(1174); + + console.log("\n\n"); +}); diff --git a/2024/day-8/day8.ts b/2024/day-8/day8.ts new file mode 100644 index 0000000..fd41eca --- /dev/null +++ b/2024/day-8/day8.ts @@ -0,0 +1,186 @@ +export function part1(input: string) { + const lines = input.split("\n"); + const height = lines.length; + const width = lines[0].length; + const antennas = new Map(); + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + for (let j = 0; j < line.length; j++) { + const char = line[j]; + if (char === ".") { + continue; + } + const [x, y] = [i, j]; + if (antennas.has(char)) { + const current = antennas.get(char); + + current.push([x, y]); + } else { + antennas.set(char, [[x, y]]); + } + } + } + + const antinodes = []; + for (const frequency of antennas.keys()) { + const antennasOnFreq = antennas.get(frequency); + for (let i = 0; i < antennasOnFreq.length; i++) { + for (let j = i + 1; j < antennasOnFreq.length; j++) { + const p1 = antennasOnFreq[i]; + const p2 = antennasOnFreq[j]; + const distanceX = Math.abs(p1[0] - p2[0]); + const distanceY = Math.abs(p1[1] - p2[1]); + const antinode1 = []; + const antinode2 = []; + + if (p1[0] > p2[0]) { + antinode1[0] = p1[0] + distanceX; + antinode2[0] = p2[0] - distanceX; + } else { + antinode1[0] = p1[0] - distanceX; + antinode2[0] = p2[0] + distanceX; + } + + if (p1[1] > p2[1]) { + antinode1[1] = p1[1] + distanceY; + antinode2[1] = p2[1] - distanceY; + } else { + antinode1[1] = p1[1] - distanceY; + antinode2[1] = p2[1] + distanceY; + } + if ( + !( + antinode1[0] < 0 || + antinode1[0] >= height || + antinode1[1] < 0 || + antinode1[1] >= width + ) + ) { + antinodes.push(antinode1); + } + if ( + !( + antinode2[0] < 0 || + antinode2[0] >= height || + antinode2[1] < 0 || + antinode2[1] >= width + ) + ) { + antinodes.push(antinode2); + } + } + } + } + const uniqueAntinodes = [...new Set(antinodes.map((x) => x.join(",")))].map( + (x) => x.split(","), + ); + + return uniqueAntinodes.length; +} + +export function part2(input: string) { + const lines = input.split("\n"); + const height = lines.length; + const width = lines[0].length; + const antennas = new Map(); + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + for (let j = 0; j < line.length; j++) { + const char = line[j]; + if (char === ".") { + continue; + } + const [x, y] = [i, j]; + if (antennas.has(char)) { + const current = antennas.get(char); + + current.push([x, y]); + } else { + antennas.set(char, [[x, y]]); + } + } + } + + const antinodes: [number, number][] = []; + for (const frequency of antennas.keys()) { + const antennasOnFreq = antennas.get(frequency); + for (let i = 0; i < antennasOnFreq.length; i++) { + for (let j = i + 1; j < antennasOnFreq.length; j++) { + const p1 = antennasOnFreq[i]; + const p2 = antennasOnFreq[j]; + const distanceX = Math.abs(p1[0] - p2[0]); + const distanceY = Math.abs(p1[1] - p2[1]); + antinodes.push(p1, p2); + if (p1[0] < p2[0] && p1[1] < p2[1]) { + let nextX = p2[0]; + let nextY = p2[1]; + while (true) { + nextX = nextX + distanceX; + nextY = nextY + distanceY; + + if (nextX >= 0 && nextX < height && nextY >= 0 && nextY < width) { + antinodes.push([nextX, nextY]); + } else { + break; + } + } + let prevX = p2[0]; + let prevY = p2[1]; + while (true) { + prevX = prevX - distanceX; + prevY = prevY - distanceY; + + if (prevX >= 0 && prevX < height && prevY >= 0 && prevY < width) { + antinodes.push([prevX, prevY]); + } else { + break; + } + } + } else if (p1[0] < p2[0] && p1[1] > p2[1]) { + let nextX = p2[0]; + let nextY = p2[1]; + while (true) { + nextX = nextX - distanceX; + nextY = nextY + distanceY; + + if (nextX >= 0 && nextX < height && nextY >= 0 && nextY < width) { + antinodes.push([nextX, nextY]); + } else { + break; + } + } + let prevX = p2[0]; + let prevY = p2[1]; + while (true) { + prevX = prevX + distanceX; + prevY = prevY - distanceY; + + if (prevX >= 0 && prevX < height && prevY >= 0 && prevY < width) { + antinodes.push([prevX, prevY]); + } else { + break; + } + } + } + } + } + } + const uniqueAntinodes = [...new Set(antinodes.map((x) => x.join(",")))].map( + (x) => x.split(","), + ); + + // display(lines, uniqueAntinodes); + + return uniqueAntinodes.length; +} + +function display(lines: string[], antinodes: string[][]) { + const nl = lines.map((x) => x.split("")); + + for (const u of antinodes) { + nl[u[0]][u[1]] === "." ? (nl[u[0]][u[1]] = "#") : null; + } + for (const x of nl) { + console.log(x.join("")); + } +} diff --git a/2024/day-8/input.txt b/2024/day-8/input.txt new file mode 100644 index 0000000..0f57ce6 --- /dev/null +++ b/2024/day-8/input.txt @@ -0,0 +1,50 @@ +................n................L..Y............. +........m......................................... +.............n.............................l...... +...............T.m..e....M........................ +...........T..y...........i.......L.....2......... +.....................e.....h.......Y........l..... +...................i......d....................... +...5..............T....o......i................... +......C.5...........m..p...o.........2....I....... +.......C.n...........d..............o....p........ +..............e........dp.....M................... +..8.........w.N.....n.p.....F..................... +.......N.......m.....D....o....................... +........DU...........y.........I.................. +..D..X......N.T....M.............................. +...........D..............2c..hl.A....M........... +.5.w.8...............h6........................... +5.....P...............d.Y.y......FA......L........ +........w.................h....................... +...................N.............................. +.............B...............u.f.................. +.........wX.......6............................... +..............XC..............Ax.................. +.P.......8......................c........f........ +...e....U.u.........s.........f............Y...... +..........U..X.........2..........W.....f......... +........P......................................... +.........s.u......................S............... +.....U...................c.....F............H..... +.........BC..........6............................ +...................s..7..A...S............3I...... +........B.s...u............S...i........H......... +..O.........................c....W....S........... +..........................a..........3......IE.... +0........P................F....................... +.............7.................W........3......... +......t.W............7........................E... +...O.....9............................E........... +.....a19.......................................... +....t.......O..........x.......................... +..................................b..............3 +........1......................b.................. +.......1....8...........x......................... +.......40......................................... +.....t...O.0...4...........................H...... +.......0..............x.......b................... +..4.......a.B..............b...........6.......... +.......t9..........17..................H.......... +........................9......................... +...........a...................................... \ No newline at end of file diff --git a/2024/day-8/test-input-2.txt b/2024/day-8/test-input-2.txt new file mode 100644 index 0000000..3d7f0bc --- /dev/null +++ b/2024/day-8/test-input-2.txt @@ -0,0 +1,12 @@ +......#....# +...#....0... +....#0....#. +..#....0.... +....0....#.. +.#....#..... +...#........ +#......#.... +........A... +.........A.. +..........#. +..........#. \ No newline at end of file diff --git a/2024/day-8/test-input.txt b/2024/day-8/test-input.txt new file mode 100644 index 0000000..de0f909 --- /dev/null +++ b/2024/day-8/test-input.txt @@ -0,0 +1,12 @@ +............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............ \ No newline at end of file diff --git a/package.json b/package.json index 01e2138..ecd8870 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "advent-of-code", "module": "index.ts", "type": "module", + "scripts": { + "prepare": "bun run scripts/prepare.ts" + }, "devDependencies": { "@biomejs/biome": "1.9.4", "@types/bun": "latest" diff --git a/scripts/prepare.ts b/scripts/prepare.ts new file mode 100644 index 0000000..55ad270 --- /dev/null +++ b/scripts/prepare.ts @@ -0,0 +1,74 @@ +import * as path from "node:path"; +import { $ } from "bun"; +async function prepare(day: number, year?: number) { + const currentYear = year ?? new Date().getFullYear(); + const fileName = `day${day}.ts`; + const testFileName = `day${day}.test.ts`; + const dir = path.join(__dirname, "..", currentYear.toString(), `day-${day}`); + console.log(`Preparing ${dir}`); + const codeTemplate = ` + export function part1(input: string) { + const lines = input.split("\\n"); + let final = 0; + return final; + } + + export function part2(input: string) { + const lines = input.split("\\n"); + let final = 0; + return final; + } + `.trim(); + + const testTemplate = ` + import { expect, test } from "bun:test"; + import * as path from "node:path"; + import { part1, part2 } from "./${fileName}"; + + test("day ${day}, part 1", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text(); + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text(); + + console.log("\\n\\n"); + + const testResult = part1(testInput); + console.log("Test data:", testResult); + expect(testResult).toEqual(0); + + // const finalResult = part1(input); + // console.log("Full data:", finalResult); + // expect(finalResult).toEqual(0); + + console.log("\\n\\n"); + }); + + test("day ${day}, part 2", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text(); + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text(); + + const testResult = part2(testInput); + console.log("\\n\\n"); + console.log("Test data:", testResult); + expect(testResult).toEqual(0); + + // const finalResult = part2(input); + // console.log("Full data:", finalResult); + // expect(finalResult).toEqual(0); + + console.log("\\n\\n"); + }); + `; + + await Bun.write(path.join(dir, testFileName), testTemplate); + await Bun.write(path.join(dir, fileName), codeTemplate); + await Bun.write(path.join(dir, "test-input.txt"), ""); + await Bun.write(path.join(dir, "input.txt"), ""); + console.log(await $`bunx biome check --write ${dir}`.text()); +} + +const [_, __, day, year] = process.argv; +void prepare(Number(day), year ? Number(year) : undefined);