|
1 |
| -type Matrix = Array<Array<string | number>>; |
| 1 | +import { TracingChannel } from "diagnostics_channel"; |
2 | 2 |
|
3 | 3 | const data = await Bun.file("input.txt").text();
|
4 | 4 | const lines = data.split("\n");
|
5 |
| -const matrix = lines.map((line) => |
6 |
| - line.split("").map((char) => { |
7 |
| - if (char === "0") return 0; |
8 |
| - if (parseInt(char)) return parseInt(char); |
9 |
| - return char; |
10 |
| - }) |
11 |
| -); |
| 5 | +const matrix = lines.map((line) => line.split("")); |
12 | 6 |
|
13 |
| -const isEqualToSymbol = (input: string | number) => { |
14 |
| - // return true if input is different from number and "." |
15 |
| - if (typeof input === "number") return false; |
16 |
| - if (input === ".") return false; |
17 |
| - return true; |
| 7 | +interface Number { |
| 8 | + value: string; |
| 9 | + i: number; |
| 10 | + j: number; |
| 11 | + hasSymbolNear: boolean; |
| 12 | +} |
| 13 | + |
| 14 | +const isNumber = (input: string): boolean => { |
| 15 | + return !isNaN(parseInt(input)); |
18 | 16 | };
|
19 | 17 |
|
20 |
| -const hasSymbolNear = (matrix: Matrix, i: number, j: number): boolean => { |
21 |
| - if (matrix[i][j + 1] !== undefined) { |
22 |
| - const right = matrix[i][j + 1]; |
| 18 | +const isDot = (input: string): boolean => { |
| 19 | + return input === "."; |
| 20 | +}; |
23 | 21 |
|
24 |
| - if (isEqualToSymbol(right)) { |
25 |
| - return true; |
26 |
| - } |
| 22 | +const symbolNear = (matrix: string[][], i: number, j: number): boolean => { |
| 23 | + const sorrounding = []; |
| 24 | + if (matrix[i - 1] !== undefined) { |
| 25 | + sorrounding.push(matrix[i - 1][j]); |
| 26 | + if (matrix[i - 1][j - 1]) sorrounding.push(matrix[i - 1][j - 1]); |
| 27 | + if (matrix[i - 1][j + 1]) sorrounding.push(matrix[i - 1][j + 1]); |
| 28 | + } |
| 29 | + if (matrix[i + 1] !== undefined) { |
| 30 | + sorrounding.push(matrix[i + 1][j]); |
| 31 | + if (matrix[i + 1][j - 1]) sorrounding.push(matrix[i + 1][j - 1]); |
| 32 | + if (matrix[i + 1][j + 1]) sorrounding.push(matrix[i + 1][j + 1]); |
| 33 | + } |
| 34 | + if (matrix[i][j - 1]) { |
| 35 | + sorrounding.push(matrix[i][j - 1]); |
| 36 | + } |
| 37 | + if (matrix[i][j + 1]) { |
| 38 | + sorrounding.push(matrix[i][j + 1]); |
27 | 39 | }
|
28 | 40 |
|
29 |
| - if (matrix[i][j - 1] !== undefined) { |
30 |
| - const left = matrix[i][j - 1]; |
| 41 | + return sorrounding.some((char) => !isNumber(char) && !isDot(char)); |
| 42 | +}; |
31 | 43 |
|
32 |
| - if (isEqualToSymbol(left)) { |
33 |
| - return true; |
| 44 | +let numbers = []; |
| 45 | +for (let i = 0; i < matrix.length; i++) { |
| 46 | + const line = matrix[i]; |
| 47 | + let number: Number = { |
| 48 | + value: "", |
| 49 | + i: 0, |
| 50 | + j: 0, |
| 51 | + hasSymbolNear: false, |
| 52 | + }; |
| 53 | + for (let j = 0; j < line.length; j++) { |
| 54 | + const char = line[j]; |
| 55 | + if (isNumber(char)) { |
| 56 | + number.value += char; |
| 57 | + number.i = i; |
| 58 | + number.j = j; |
| 59 | + if (!number.hasSymbolNear) |
| 60 | + number.hasSymbolNear = symbolNear(matrix, i, j); |
| 61 | + } |
| 62 | + if ( |
| 63 | + j + 1 === line.length || |
| 64 | + ((isDot(char) || !isNumber(char)) && number.value.length > 0) |
| 65 | + ) { |
| 66 | + if (number.hasSymbolNear) { |
| 67 | + numbers.push(number); |
| 68 | + } |
| 69 | + number = { |
| 70 | + value: "", |
| 71 | + i: 0, |
| 72 | + j: 0, |
| 73 | + hasSymbolNear: false, |
| 74 | + }; |
34 | 75 | }
|
35 | 76 | }
|
| 77 | +} |
36 | 78 |
|
37 |
| - if (matrix[i - 1] !== undefined) { |
38 |
| - const topLeft = matrix[i - 1][j - 1]; |
39 |
| - const top = matrix[i - 1][j]; |
40 |
| - const topRight = matrix[i - 1][j + 1]; |
41 |
| - |
42 |
| - if (isEqualToSymbol(topLeft)) { |
43 |
| - return true; |
| 79 | +const partsNumber = numbers.reduce((a, b) => a + parseInt(b.value), 0); |
| 80 | +console.log("partsNumber", partsNumber); |
| 81 | + |
| 82 | +const buildNumber = ( |
| 83 | + matrix: string[][], |
| 84 | + i: number, |
| 85 | + j: number, |
| 86 | + mode: string |
| 87 | +) => { |
| 88 | + let number: string = ""; |
| 89 | + let number2: string = ""; |
| 90 | + |
| 91 | + if (mode === "top") { |
| 92 | + let x = j - 1; |
| 93 | + let y = i - 1; |
| 94 | + while (isNumber(matrix[y][x])) { |
| 95 | + x--; |
44 | 96 | }
|
45 |
| - |
46 |
| - if (isEqualToSymbol(top)) { |
47 |
| - return true; |
| 97 | + x++; |
| 98 | + if (!isNumber(matrix[y][x])) x++; |
| 99 | + while (isNumber(matrix[y][x])) { |
| 100 | + number += matrix[y][x]; |
| 101 | + matrix[y][x] = "."; |
| 102 | + x++; |
48 | 103 | }
|
49 |
| - |
50 |
| - if (isEqualToSymbol(topRight)) { |
51 |
| - return true; |
| 104 | + if (matrix[y][x] === "." && matrix[y + 1][x] === "*") x++; |
| 105 | + while (isNumber(matrix[y][x])) { |
| 106 | + number2 += matrix[y][x]; |
| 107 | + matrix[y][x] = "."; |
| 108 | + x++; |
52 | 109 | }
|
53 |
| - } |
54 |
| - |
55 |
| - if (matrix[i + 1] !== undefined) { |
56 |
| - const bottomLeft = matrix[i + 1][j - 1]; |
57 |
| - const bottom = matrix[i + 1][j]; |
58 |
| - const bottomRight = matrix[i + 1][j + 1]; |
59 |
| - |
60 |
| - if (isEqualToSymbol(bottomLeft)) { |
61 |
| - return true; |
| 110 | + } else if (mode === "bottom") { |
| 111 | + let x = j - 1; |
| 112 | + let y = i + 1; |
| 113 | + while (isNumber(matrix[y][x])) { |
| 114 | + x--; |
62 | 115 | }
|
63 |
| - |
64 |
| - if (isEqualToSymbol(bottom)) { |
65 |
| - return true; |
| 116 | + x++; |
| 117 | + if (!isNumber(matrix[y][x])) x++; |
| 118 | + while (isNumber(matrix[y][x])) { |
| 119 | + number += matrix[y][x]; |
| 120 | + matrix[y][x] = "."; |
| 121 | + x++; |
66 | 122 | }
|
67 |
| - |
68 |
| - if (isEqualToSymbol(bottomRight)) { |
69 |
| - return true; |
| 123 | + if (matrix[y][x] === "." && matrix[y - 1][x] === "*") x++; |
| 124 | + while (isNumber(matrix[y][x])) { |
| 125 | + number2 += matrix[y][x]; |
| 126 | + matrix[y][x] = "."; |
| 127 | + x++; |
| 128 | + } |
| 129 | + } else if (mode === "left") { |
| 130 | + let x = j - 1; |
| 131 | + let y = i; |
| 132 | + while (isNumber(matrix[y][x])) { |
| 133 | + x--; |
| 134 | + } |
| 135 | + x++; |
| 136 | + if (!isNumber(matrix[y][x]) && matrix[y][x] !== "*") x++; |
| 137 | + while (isNumber(matrix[y][x])) { |
| 138 | + number += matrix[y][x]; |
| 139 | + matrix[y][x] = "."; |
| 140 | + x++; |
| 141 | + } |
| 142 | + } else if (mode === "right") { |
| 143 | + let x = j + 1; |
| 144 | + let y = i; |
| 145 | + while (isNumber(matrix[y][x])) { |
| 146 | + number += matrix[y][x]; |
| 147 | + matrix[y][x] = "."; |
| 148 | + x++; |
70 | 149 | }
|
71 | 150 | }
|
72 | 151 |
|
73 |
| - return false; |
| 152 | + return [number, number2]; |
74 | 153 | };
|
75 | 154 |
|
76 |
| -const buildNumber = (matrix: Matrix, i: number, j: number) => { |
77 |
| - let peekPosition = j; |
78 |
| - let number = ""; |
79 |
| - while ( |
80 |
| - matrix[i][peekPosition] !== "." && |
81 |
| - !isEqualToSymbol(matrix[i][peekPosition]) |
82 |
| - ) { |
83 |
| - const char = matrix[i][peekPosition].toString(); |
84 |
| - number += char; |
85 |
| - peekPosition++; |
86 |
| - } |
87 |
| - return number; |
88 |
| -}; |
89 |
| - |
90 |
| -let numbers = []; |
91 |
| -for (let i = 0; i < matrix.length; i++) { |
| 155 | +let gearRatiosSum = 0; |
| 156 | +let num: number = 0; |
| 157 | +for (let i = 1; i < matrix.length - 1; i++) { |
92 | 158 | const line = matrix[i];
|
93 |
| - for (let j = 0; j < line.length; j++) { |
| 159 | + for (let j = 1; j < line.length - 1; j++) { |
94 | 160 | const char = line[j];
|
95 |
| - if (typeof char === "number") { |
96 |
| - const res = hasSymbolNear(matrix, i, j); |
97 |
| - if (res) { |
98 |
| - // has symbol near |
99 |
| - let number = buildNumber(matrix, i, j); |
100 |
| - numbers.push(number); |
101 |
| - j += number.length; |
102 |
| - } else { |
103 |
| - // no symbol near |
104 |
| - let peekPosition = j + 1; |
105 |
| - let hasSymbolAfter = false; |
106 |
| - while (typeof matrix[i][peekPosition] === "number") { |
107 |
| - if (matrix[i][peekPosition] === ".") break; |
108 |
| - if (hasSymbolNear(matrix, i, peekPosition)) { |
109 |
| - hasSymbolAfter = true; |
110 |
| - let number = buildNumber(matrix, i, j); |
111 |
| - numbers.push(number); |
112 |
| - j += number.length; |
113 |
| - break; |
114 |
| - } |
115 |
| - peekPosition++; |
116 |
| - } |
| 161 | + if (char === "*") { |
| 162 | + const top = buildNumber(matrix, i, j, "top"); |
| 163 | + const bottom = buildNumber(matrix, i, j, "bottom"); |
| 164 | + const left = buildNumber(matrix, i, j, "left"); |
| 165 | + const right = buildNumber(matrix, i, j, "right"); |
| 166 | + const numberiBelli = [top, bottom, left, right] |
| 167 | + .flat() |
| 168 | + .map((n) => parseInt(n)) |
| 169 | + .filter((n) => !isNaN(n)); |
| 170 | + |
| 171 | + if (numberiBelli.length > 1) { |
| 172 | + matrix[i][j] = "."; |
| 173 | + } |
| 174 | + if (numberiBelli.length === 2) { |
| 175 | + gearRatiosSum += numberiBelli[0] * numberiBelli[1]; |
| 176 | + num++; |
117 | 177 | }
|
118 | 178 | }
|
119 | 179 | }
|
120 | 180 | }
|
121 | 181 |
|
122 |
| -console.log(numbers.reduce((acc, curr) => acc + parseInt(curr), 0)); |
123 |
| -console.log(numbers); |
124 |
| - |
125 |
| -const data2 = await Bun.file("input.txt").text(); |
126 |
| -const lines2 = data2.split("\n"); |
127 |
| -const grid = lines2.map((line) => line.split(".")); |
128 |
| -console.log(grid); |
| 182 | +console.log("gearRatiosSum", gearRatiosSum); |
0 commit comments