-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path9.ts
90 lines (80 loc) · 3.08 KB
/
9.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
88
89
90
import * as fs from 'fs';
import { compact, differenceWith, flatMap, sum, uniqBy } from 'lodash';
import { log } from './utils';
type ValuedCoordinates = { rowIndex: number; colIndex: number; value: number };
const input: number[][] = compact(fs.readFileSync('./9.txt', { encoding: 'utf-8' }).split('\n')).map(line =>
line.split('').map(Number),
);
const height = input.length;
const width = input[0].length;
function part1(): void {
function getRiskLevel(height: number): number {
return 1 + height;
}
const result = sum(
getLowPoints(input)
.map(x => x.value)
.map(getRiskLevel),
);
log(result);
}
function getLowPoints(lines: typeof input): Array<ValuedCoordinates> {
function isLowPoint(lines: typeof input, rowIndex: number, value: number, colIndex: number): boolean {
return getNeighbours(rowIndex, colIndex, lines)
.map(neighbour => neighbour.value)
.every(neighbour => value < neighbour);
}
return flatMap(input, (line, rowIndex) => {
return compact(
line.map((value, colIndex) =>
isLowPoint(lines, rowIndex, value, colIndex) ? { rowIndex, colIndex, value } : undefined,
),
);
});
}
function getNeighbours(rowIndex: number, colIndex: number, lines: typeof input): ValuedCoordinates[] {
return compact([
rowIndex > 0 ? { value: lines[rowIndex - 1][colIndex], rowIndex: rowIndex - 1, colIndex } : undefined,
colIndex > 0 ? { value: lines[rowIndex][colIndex - 1], rowIndex, colIndex: colIndex - 1 } : undefined,
colIndex < width - 1
? { value: lines[rowIndex][colIndex + 1], rowIndex, colIndex: colIndex + 1 }
: undefined,
rowIndex < height - 1
? { value: lines[rowIndex + 1][colIndex], rowIndex: rowIndex + 1, colIndex }
: undefined,
]);
}
function part2(): void {
function getBasin(
point: ValuedCoordinates,
lines: typeof input,
visitedPoints: ValuedCoordinates[],
): ValuedCoordinates[] {
visitedPoints.push(point);
const neighbours = differenceWith(
getNeighbours(point.rowIndex, point.colIndex, lines),
visitedPoints,
(neighbour, visitedPoint) =>
neighbour.colIndex === visitedPoint.colIndex && neighbour.rowIndex === visitedPoint.rowIndex,
);
let basin: ValuedCoordinates[] = [point];
for (let neighbour of neighbours) {
if (neighbour.value < 9 && neighbour.value > point.value) {
basin.push(...getBasin(neighbour, lines, visitedPoints));
}
}
return basin;
}
const visitedPoints: ValuedCoordinates[] = [];
const lowPoints = getLowPoints(input);
const basins = lowPoints.map(point => getBasin(point, input, visitedPoints));
const result = basins
.map(basin => uniqBy(basin, point => `${point.rowIndex},${point.colIndex}`))
.map(x => x.length)
.sort((a, b) => a - b)
.slice(-3)
.reduce(Math.imul);
log(result);
}
part1();
part2();