-
Notifications
You must be signed in to change notification settings - Fork 0
/
day09.ts
99 lines (85 loc) · 2.95 KB
/
day09.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
91
92
93
94
95
96
97
98
99
// import fs and lodash
import * as _ from "lodash";
import * as fs from "fs";
// function reads file which is a 2d array of single digit numbers
// returns a 2d array of single digit numbers
function readFile(fileName: string): number[][] {
const input = fs.readFileSync(fileName, "utf8");
const lines = input.split("\n");
const numbers = lines.map((line) =>
line.split("").map((char) => parseInt(char))
);
return numbers;
}
// algorithm to find list of local minima in numbers
// local minima if smaller than left, right, top and bottom neighbours
// returns a list of local minima and their coordinates
function findLocalMinima(numbers: number[][]) {
const localMinima: number[] = [];
const localMinimaCoordinates: number[][] = [];
for (let i = 0; i < numbers.length; i++) {
for (let j = 0; j < numbers[i].length; j++) {
if (
(i === 0 || numbers[i][j] < numbers[i - 1][j]) &&
(j === 0 || numbers[i][j] < numbers[i][j - 1]) &&
(i === numbers.length - 1 || numbers[i][j] < numbers[i + 1][j]) &&
(j === numbers[i].length - 1 || numbers[i][j] < numbers[i][j + 1])
) {
localMinima.push(numbers[i][j]);
localMinimaCoordinates.push([i, j]);
}
}
}
return {
localMinima,
localMinimaCoordinates,
};
}
// function with height map input of single digit numbers as array, second parameter is the x and y coordinate of the starting point
// flood fill outwards from starting point until digit 9 is reached
// return the size of the filled area
function floodFill(numbers: number[][], x: number, y: number): number {
let size = 0;
if (numbers[x][y] === 9) {
return 1;
}
numbers[x][y] = 9;
size = 1;
if (x - 1 >= 0 && numbers[x - 1][y] !== 9) {
size += floodFill(numbers, x - 1, y);
}
if (x + 1 < numbers.length && numbers[x + 1][y] !== 9) {
size += floodFill(numbers, x + 1, y);
}
if (y - 1 >= 0 && numbers[x][y - 1] !== 9) {
size += floodFill(numbers, x, y - 1);
}
if (y + 1 < numbers[x].length && numbers[x][y + 1] !== 9) {
size += floodFill(numbers, x, y + 1);
}
return size;
}
function part1() {
// read file day09input
const numbers = readFile("day09input");
// find local minima
const localMinima = findLocalMinima(numbers).localMinima;
// sum up all local minima and add length of local minima
const sum = _.sum(localMinima) + localMinima.length;
// print result
console.log(sum);
}
function part2() {
// read file day09input
const numbers = readFile("day09input");
// find local minima
const localMinima = findLocalMinima(numbers).localMinimaCoordinates;
// iterst over local minima and flood fill from each local minima, store the size of the filled area in array
const sizes = localMinima.map(([i, j]) => floodFill(numbers, i, j));
// find largest 3 sizes and multiply them
const largest3 = _.sortBy(sizes).slice(-3);
const result = _.reduce(largest3, (a, b) => a * b);
// print result
console.log(result);
}
part2();