Skip to content

Commit 04aa1db

Browse files
committed
[ts] 2024:06: Solve part 1
1 parent 64091b1 commit 04aa1db

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed

2024/day06/day06.ts

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// @ts-ignore - tl_ls is missing @types/node
2+
import { EOL } from "node:os";
3+
// @ts-ignore - tl_ls doesn't know about Bun
4+
const inputLines = (await Bun.file("input").text()).trim().split(EOL);
5+
6+
const OBSTACLE_MARKER = "#";
7+
8+
class Vector {
9+
x: number;
10+
y: number;
11+
12+
constructor(x: number, y: number) {
13+
this.x = x;
14+
this.y = y;
15+
}
16+
17+
add(other: Vector): Vector { return new Vector(this.x + other.x, this.y + other.y); }
18+
neg(): Vector { return new Vector(this.x * -1, this.y * -1); }
19+
eq(other: Vector) { return other.x == this.x && other.y == this.y; }
20+
toString() { return `(${this.x}|${this.y})`; }
21+
cpy() { return new Vector(this.x, this.y); }
22+
}
23+
const OUT_OF_BOUNDS: Vector = new Vector(-1, -1);
24+
const GUARD_LOCATION_MAP = {
25+
"v": new Vector(0, 1),
26+
"^": new Vector(0, -1),
27+
"<": new Vector(-1, 0),
28+
">": new Vector(1, 0)
29+
};
30+
const DIRECTION_ORDER = [
31+
GUARD_LOCATION_MAP["^"], GUARD_LOCATION_MAP[">"],
32+
GUARD_LOCATION_MAP["v"], GUARD_LOCATION_MAP["<"],
33+
GUARD_LOCATION_MAP["^"]
34+
]
35+
36+
type Grid = Array<Array<string>>;
37+
class Laboratory {
38+
height: number;
39+
width: number;
40+
41+
obstacles: VectorList;
42+
guard: Guard;
43+
44+
constructor(input: Grid) {
45+
this.height = input.length;
46+
this.width = input[0].length;
47+
48+
this.obstacles = new VectorList();
49+
for (let y = 0; y < this.height; y++) {
50+
for (let x = 0; x < this.width; x++) {
51+
const char = input[y][x];
52+
if (char == OBSTACLE_MARKER) this.obstacles.push(new Vector(x, y));
53+
else if (GUARD_LOCATION_MAP.hasOwnProperty(char)) {
54+
this.guard = new Guard([new Vector(x, y), GUARD_LOCATION_MAP[char], this]);
55+
}
56+
}
57+
}
58+
}
59+
}
60+
type Position = [Vector, Vector, Laboratory];
61+
function cpyPosition(position: Position): Position {
62+
return [position[0].cpy(), position[1].cpy(), position[2]]
63+
}
64+
class History extends Array<Position> {
65+
includes(pos: Position) {
66+
for (let checkPosition of this) {
67+
if (checkPosition[0].eq(pos[0])) return true;
68+
}
69+
return false;
70+
}
71+
}
72+
class VectorList extends Array<Vector> {
73+
includes(vec: Vector) {
74+
for (let vector of this) {
75+
if (vector.eq(vec)) return true;
76+
}
77+
return false;
78+
}
79+
}
80+
81+
class Guard {
82+
position: Position;
83+
history: History = []
84+
85+
constructor(position: Position) {
86+
this.position = position;
87+
}
88+
89+
facing(): Vector {
90+
return this.position[0].add(this.position[1]);
91+
}
92+
93+
rotateRight() {
94+
for (let directionInx = 0; directionInx < DIRECTION_ORDER.length; directionInx++) {
95+
if (this.position[1].eq(DIRECTION_ORDER[directionInx])) {
96+
this.position[1] = DIRECTION_ORDER[directionInx + 1];
97+
return;
98+
}
99+
}
100+
}
101+
102+
tick() {
103+
const newLocation = this.facing();
104+
if (this.position[2].obstacles.includes(newLocation)) this.rotateRight();
105+
else if (
106+
(newLocation.x >= this.position[2].width)
107+
|| (newLocation.x < 0)
108+
|| (newLocation.y >= this.position[2].height)
109+
|| (newLocation.y < 0)
110+
) {
111+
this.position[0] = OUT_OF_BOUNDS;
112+
return;
113+
} else this.position[0] = newLocation;
114+
115+
if (this.history.includes(this.position)) {
116+
console.warn(
117+
"Duplicate guard loc+dir:",
118+
this.position[0].toString(),
119+
this.position[1].toString()
120+
);
121+
}
122+
this.history.push(cpyPosition(this.position));
123+
}
124+
125+
isInField() { return !this.position[0].eq(OUT_OF_BOUNDS); }
126+
}
127+
128+
const laboratory = new Laboratory(inputLines.map((line: string) => line.split("")));
129+
while (laboratory.guard.isInField()) {
130+
laboratory.guard.tick();
131+
}
132+
133+
let uniqueSpots: VectorList = new VectorList();
134+
const solution1 = laboratory.guard.history.reduce((acc, historyEntry) => {
135+
if (!uniqueSpots.includes(historyEntry[0])) {
136+
uniqueSpots.push(historyEntry[0]);
137+
acc += 1;
138+
}
139+
return acc;
140+
}, 0);
141+
142+
// @ts-ignore
143+
Bun.write(
144+
// @ts-ignore
145+
Bun.file("debug"),
146+
uniqueSpots.map((spot, inx) => (
147+
spot.toString()
148+
+ ((inx+1) % 10 == 0 ? EOL : " "))
149+
)
150+
);
151+
152+
console.log("Part 1:", solution1);

0 commit comments

Comments
 (0)