Skip to content

Commit aa47e65

Browse files
committed
day 14
1 parent e54ff44 commit aa47e65

File tree

4 files changed

+117
-2
lines changed

4 files changed

+117
-2
lines changed

days/14/main.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { loadInput } from "utils";
2+
3+
const defaultWidth = 101;
4+
const defaultHeight = 103;
5+
6+
export function part1(
7+
input: Array<string>,
8+
width = defaultWidth,
9+
height = defaultHeight,
10+
) {
11+
const simulate100 = simulate(100, width, height);
12+
const positions = input.map(parseInput).map(simulate100);
13+
const halfWidth = Math.floor(width / 2);
14+
const halfHeight = Math.floor(height / 2);
15+
let q1 = 0, q2 = 0, q3 = 0, q4 = 0;
16+
for (const { x, y } of positions) {
17+
if (x < halfWidth && y < halfHeight) {
18+
q1++;
19+
} else if (x > halfWidth && y < halfHeight) {
20+
q2++;
21+
} else if (x < halfWidth && y > halfHeight) {
22+
q3++;
23+
} else if (x > halfWidth && y > halfHeight) {
24+
q4++;
25+
}
26+
}
27+
return q1 * q2 * q3 * q4;
28+
}
29+
30+
export function part2(input: Array<string>) {
31+
const robots = input.map(parseInput);
32+
return simulateUntilUnique(robots, defaultWidth, defaultHeight);
33+
}
34+
35+
type Robot = {
36+
x: number;
37+
y: number;
38+
vx: number;
39+
vy: number;
40+
};
41+
42+
function simulate(seconds: number, width: number, height: number) {
43+
return (robot: Robot) => {
44+
const x = (((robot.x + robot.vx * seconds) % width) + width) % width;
45+
const y = (((robot.y + robot.vy * seconds) % height) + height) % height;
46+
return { x, y };
47+
};
48+
}
49+
50+
function simulateUntilUnique(
51+
robots: Array<Robot>,
52+
width: number,
53+
height: number,
54+
) {
55+
outer: for (let s = 1;; s++) {
56+
const positions = new Set<string>();
57+
const simulateS = simulate(s, width, height);
58+
for (const robot of robots) {
59+
const { x, y } = simulateS(robot);
60+
const key = `${x},${y}`;
61+
if (positions.has(key)) {
62+
continue outer;
63+
}
64+
positions.add(key);
65+
}
66+
return s;
67+
}
68+
}
69+
70+
function parseInput(line: string): Robot {
71+
const [l, r] = line.split(" v=");
72+
const [x, y] = l.split("=")[1].split(",").map(Number);
73+
const [vx, vy] = r.split(",").map(Number);
74+
return { x, y, vx, vy };
75+
}
76+
77+
if (import.meta.main) {
78+
console.log(part1(await loadInput(14)));
79+
console.log(part2(await loadInput(14)));
80+
}

days/14/main_test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { expect } from "@std/expect";
2+
import { describe, it } from "@std/testing/bdd";
3+
import { part1, part2 } from "./main.ts";
4+
import { loadInput } from "utils";
5+
6+
describe("day 14 example", () => {
7+
const input = [
8+
"p=0,4 v=3,-3",
9+
"p=6,3 v=-1,-3",
10+
"p=10,3 v=-1,2",
11+
"p=2,0 v=2,-1",
12+
"p=0,0 v=1,3",
13+
"p=3,0 v=-2,-2",
14+
"p=7,6 v=-1,-3",
15+
"p=3,0 v=-1,-2",
16+
"p=9,3 v=2,3",
17+
"p=7,3 v=-1,2",
18+
"p=2,4 v=2,-3",
19+
"p=9,5 v=-3,-3",
20+
];
21+
22+
it("part 1", () => {
23+
expect(part1(input, 11, 7)).toBe(12);
24+
});
25+
});
26+
27+
describe("day 14 solution", () => {
28+
it("part 1", async () => {
29+
expect(part1(await loadInput(14))).toBe(229839456);
30+
});
31+
32+
it("part 2", async () => {
33+
expect(part2(await loadInput(14))).toBe(7138);
34+
});
35+
});

days/mod.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ type Solution = { part1: PartFunction; part2: PartFunction };
33

44
const days = new Map<number, Solution>();
55

6-
for (const day of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13]) {
6+
for (const day of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]) {
77
days.set(day, await import(`./${day}/main.ts`));
88
}
99

inputs

0 commit comments

Comments
 (0)