-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.ts
executable file
·110 lines (89 loc) · 2.56 KB
/
main.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
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env deno run --allow-read
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
import { addCoords, Coord, CoordSet } from "../../2020/utils.ts";
const FLASH_AFTER = 9;
const parseInput = (string: string): number[][] =>
string.trim().split("\n").map((line) => {
return line.trim().split("").map((n) => parseInt(n, 10));
});
const text = await Deno.readTextFile("input.txt");
export const input = parseInput(text);
const neighborDirections: Coord[] = [
[-1, -1],
[+0, -1],
[+1, -1],
[-1, +0],
[+1, +0],
[-1, +1],
[+0, +1],
[+1, +1],
];
type RunFlashesCallbackParams = {
step: number;
flashed: CoordSet;
state: number[][];
};
export const runFlashesUntil = <R>(
input: number[][],
callback: (params: RunFlashesCallbackParams) => R | undefined,
): R => {
const state = input.map((line) => [...line]);
const isInBounds = ([x, y]: Coord) =>
state[y] !== undefined && state[y][x] !== undefined;
for (let step = 1; true; step++) {
const flashed = new CoordSet();
const increase = (coord: Coord) => {
if (flashed.has(coord)) return;
const [x, y] = coord;
state[y][x]++;
if (state[y][x] > FLASH_AFTER) flash(coord);
};
const flash = (coord: Coord) => {
flashed.add(coord);
const [x, y] = coord;
state[y][x] = 0;
neighborDirections.forEach((neighborDirection) => {
const neighbor = addCoords(neighborDirection, coord);
if (!isInBounds(neighbor)) return;
increase(neighbor);
});
};
for (let y = 0; y < state.length; y++) {
for (let x = 0; x < state[y].length; x++) {
increase([x, y]);
}
}
const callbackResult = callback({ step, flashed, state });
if (callbackResult !== undefined) return callbackResult;
}
};
const part1 = (input: number[][]): number => {
let totalFlashedCount = 0;
runFlashesUntil(input, ({ step, flashed }) => {
totalFlashedCount += flashed.size;
if (step === 100) return true;
});
return totalFlashedCount;
};
const example = parseInput(`
5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526
`);
assertEquals(part1(example), 1656);
console.log("Result part 1: " + part1(input));
const part2 = (input: number[][]): number => {
const inputCount = input[0].length * input.length;
return runFlashesUntil(input, ({ step, flashed }) => {
if (flashed.size === inputCount) return step;
});
};
assertEquals(part2(example), 195);
console.log("Result part 2: " + part2(input));