-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
92 lines (76 loc) · 2.49 KB
/
index.js
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
'use strict';
const fs = require('node:fs');
const input = process.argv.length > 2 && process.argv[2] === 'ex' ? 'example' : 'input';
const text = String(fs.readFileSync(`./${input}.txt`));
let rows = text.split('\n');
function symbolInAreaOfNumber(s, n) {
return n.area.rows.includes(s.row) && n.area.start <= s.index && n.area.end >= s.index;
}
const nmbrRegex = /\d+/g;
const matchedNumbers = [];
for (let r = 0; r < rows.length; r++) {
let match = null;
while ((match = nmbrRegex.exec(rows[r])) != null) {
const numberIndex = match.index;
const length = match[0].length;
// console.log(`Number in row ${r + 1} @ position ${numberIndex}: ${match[0]} (${length} digits)`);
matchedNumbers.push({
valid: false,
value: parseInt(match[0]),
area: {
row: r,
rows: [r, r - 1, r + 1].filter(rr => rr >= 0 && rr < rows.length), // valid in rows
start: numberIndex > 0 ? numberIndex - 1 : numberIndex,
end: numberIndex + length,
}
});
}
}
/*
...xxxxxx.... 0
...x1234x.... 1
...xxxxxx.... 2
*/
const symbolRexexp = /[^\d.]/g; // no numbers or dots
const matchedSymbols = [];
for (let r = 0; r < rows.length; r++) {
let match = null;
while ((match = symbolRexexp.exec(rows[r])) != null) {
const symbolIndex = match.index;
// console.log(`Symbol in row ${r + 1} @ position ${symbolIndex}: ${match[0]}`);
matchedSymbols.push({
value: match[0],
isGear: match[0] === '*',
partNumbers: [],
index: symbolIndex,
row: r,
});
}
}
// Part 1
for (const n of matchedNumbers) {
for (const s of matchedSymbols) {
if (symbolInAreaOfNumber(s, n)) {
// console.log(`${n.value} (row ${n.area.row + 1}) is valid by sybol ${s.value} in row ${s.row + 1}`);
n.valid = true;
}
}
}
//console.log(JSON.stringify(matchedNumbers, null, 2));
// Part 2
for (const s of matchedSymbols) {
for (const n of matchedNumbers) {
if (s.isGear && symbolInAreaOfNumber(s, n)) {
s.partNumbers.push(n.value);
}
}
}
console.log('Round 1:');
console.log(matchedNumbers.reduce((acc, n) => n.valid ? acc + n.value : acc, 0));
console.log('Round 2:');
console.log(matchedSymbols.reduce((acc, s) => {
if (s.isGear && s.partNumbers.length === 2) {
acc += s.partNumbers[0] * s.partNumbers[1];
}
return acc;
}, 0));