mirror of
https://github.com/ershisan99/advent-of-code.git
synced 2025-12-16 12:32:49 +00:00
2024 day 8
This commit is contained in:
40
2024/day-8/day8.test.ts
Normal file
40
2024/day-8/day8.test.ts
Normal file
@@ -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");
|
||||||
|
});
|
||||||
186
2024/day-8/day8.ts
Normal file
186
2024/day-8/day8.ts
Normal file
@@ -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(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
50
2024/day-8/input.txt
Normal file
50
2024/day-8/input.txt
Normal file
@@ -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......................................
|
||||||
12
2024/day-8/test-input-2.txt
Normal file
12
2024/day-8/test-input-2.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
......#....#
|
||||||
|
...#....0...
|
||||||
|
....#0....#.
|
||||||
|
..#....0....
|
||||||
|
....0....#..
|
||||||
|
.#....#.....
|
||||||
|
...#........
|
||||||
|
#......#....
|
||||||
|
........A...
|
||||||
|
.........A..
|
||||||
|
..........#.
|
||||||
|
..........#.
|
||||||
12
2024/day-8/test-input.txt
Normal file
12
2024/day-8/test-input.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
............
|
||||||
|
........0...
|
||||||
|
.....0......
|
||||||
|
.......0....
|
||||||
|
....0.......
|
||||||
|
......A.....
|
||||||
|
............
|
||||||
|
............
|
||||||
|
........A...
|
||||||
|
.........A..
|
||||||
|
............
|
||||||
|
............
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
"name": "advent-of-code",
|
"name": "advent-of-code",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"prepare": "bun run scripts/prepare.ts"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/bun": "latest"
|
"@types/bun": "latest"
|
||||||
|
|||||||
74
scripts/prepare.ts
Normal file
74
scripts/prepare.ts
Normal file
@@ -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);
|
||||||
Reference in New Issue
Block a user