-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path05.ts
87 lines (81 loc) · 2.5 KB
/
05.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { V2, Vec2 } from "../../common/vector2.ts";
function parseLines(input: string): [Vec2, Vec2][] {
// Each line is separated by a line break
return input.split("\n")
.map((line) => {
// Points in the line are separated by an arrow
const [from, to] = line.split(" -> ")
// Values of the position are separated by comma
.map((points) => {
const [x, y] = points.split(",")
.map((x) => parseInt(x, 10));
return { x, y };
});
return [from, to] as [Vec2, Vec2];
});
}
type LineDirection = "horizontal" | "vertical" | "diagonal";
function getDirection([a, b]: [Vec2, Vec2]): LineDirection {
if (a.y === b.y) return "horizontal";
if (a.x === b.x) return "vertical";
return "diagonal";
}
function isOrthogonal(line: [Vec2, Vec2]): boolean {
return getDirection(line) !== "diagonal";
}
function getLineToPoints([a, b]: [Vec2, Vec2]): Vec2[] {
const points: Vec2[] = [];
const direction = getDirection([a, b]);
if (direction === "vertical") {
const minY = Math.min(a.y, b.y);
const maxY = Math.max(a.y, b.y);
for (let y = minY; y <= maxY; y++) {
points.push({ x: a.x, y });
}
return points;
}
if (direction === "horizontal") {
const minX = Math.min(a.x, b.x);
const maxX = Math.max(a.x, b.x);
for (let x = minX; x <= maxX; x++) {
points.push({ x, y: a.y });
}
return points;
}
if (direction === "diagonal") {
let steps = Math.abs(a.x - b.x);
let x = a.x;
let y = a.y;
points.push({ x, y });
while (steps--) {
x += a.x > b.x ? -1 : 1;
y += a.y > b.y ? -1 : 1;
points.push({ x, y });
}
}
return points;
}
function countOverlapPoints(lines: [Vec2, Vec2][]): number {
const occupied: Record<string, number> = {};
const addPoint = (pos: string) => {
occupied[pos] = occupied[pos] ? occupied[pos] + 1 : 1;
};
lines.forEach((line) => {
getLineToPoints(line).forEach((point) => {
addPoint(V2.str(point));
});
});
return Object.values(occupied).filter((count) => count > 1).length;
}
// Consider horizontal and vertical lines
// "At how many points do at least two lines overlap?"
export function part1(input: string) {
const lines = parseLines(input);
return countOverlapPoints(lines.filter(isOrthogonal));
}
// Consider horizontal, vertical and diagonal lines
// "At how many points do at least two lines overlap?"
export function part2(input: string) {
const lines = parseLines(input);
return countOverlapPoints(lines);
}