3b redux
I took out the union find, the code is simpler and more readable now. I also leaned in to using null values, which is gross but whatever, it works.
void day3s() {
List lines = [
for (String? line = stdin.readLineSync();
line != null;
line = stdin.readLineSync())
line
];
// lazy processing + memoization
List> digs = [for (int i = 0; i < lines.length; i++) Map()];
int? isDigitMem(int r, int c) {
if (r < 0 || r > lines.length || c < 0 || c > lines[0].length) return null;
return digs[r].putIfAbsent(c, () => isDigit(lines[r][c]));
}
int stoi(int row, int col) {
int acc = 0;
for (int i = col; i < lines[0].length; i++) {
int? d = isDigitMem(row, i);
if (d != null) {
acc = (acc * 10) + d;
} else {
break;
}
}
return acc;
}
int? stoiSearch(int row, int col) {
assert(row >= 0 && col >= 0 && row < lines.length && col < lines[0].length);
if (isDigitMem(row, col) == null) {
return null;
}
int i = col - 1;
while (i >= 0) {
if (isDigitMem(row, i) == null) {
return stoi(row, i + 1);
}
i--;
}
return stoi(row, 0);
}
List> s2i = [for (int i = 0; i < lines.length; i++) Map()];
int? stoiSearchMem(int row, int col) {
if (row < 0 || row >= lines.length) return null;
if (col < 0 || col >= lines[0].length) return null;
return s2i[row].putIfAbsent(col, () => stoiSearch(row, col));
}
int count = 0;
for (int i = 0; i < lines.length; i++) {
for (int j = 0; j < lines[0].length; j++) {
if (lines[i][j] != "*") {
continue;
}
List gearVals = List.empty(growable: true);
for (int x = -1; x <= 1; x++) {
int? left = stoiSearchMem(i + x, j - 1);
int? mid = stoiSearchMem(i + x, j);
int? right = stoiSearchMem(i + x, j + 1);
if (isDigitMem(i + x, j) == null) {
if (left != null) {
gearVals.add(left);
}
if (right != null) {
gearVals.add(right);
}
} else if (left != null) {
gearVals.add(left);
} else if (mid != null) {
gearVals.add(mid);
} else if (right != null) {
gearVals.add(right);
}
}
if (gearVals.length == 2) {
count += gearVals[0] * gearVals[1];
}
}
}
print(count);
}