Dart
I’m cheating a bit by posting this as it does take 11s for the full part 2 solution, but having tracked down and eliminated the excessively long path for part 1, I can’t be bothered to do it again for part 2.
I’m an idiot. Avoiding recursively adding the same points to the seen
set dropped total runtime to a hair under 0.5s, so line-seconds are around 35.
Map, Set>> seen = {};
Map fire(List> grid, Point here, Point dir) {
seen = {};
return _fire(grid, here, dir);
}
Map, Set>> _fire(
List> grid, Point here, Point dir) {
while (true) {
here += dir;
if (!here.x.between(0, grid.first.length - 1) ||
!here.y.between(0, grid.length - 1)) {
return seen;
}
if (seen[here]?.contains(dir) ?? false) return seen;
seen[here] = (seen[here] ?? >{})..add(dir);
Point split() {
_fire(grid, here, Point(-dir.y, -dir.x));
return Point(dir.y, dir.x);
}
dir = switch (grid[here.y][here.x]) {
'/' => Point(-dir.y, -dir.x),
r'\' => Point(dir.y, dir.x),
'|' => (dir.x.abs() == 1) ? split() : dir,
'-' => (dir.y.abs() == 1) ? split() : dir,
_ => dir,
};
}
}
parse(List lines) => lines.map((e) => e.split('').toList()).toList();
part1(List lines) =>
fire(parse(lines), Point(-1, 0), Point(1, 0)).length;
part2(List lines) {
var grid = parse(lines);
var ret = 0.to(grid.length).fold(
0,
(s, t) => [
s,
fire(grid, Point(-1, t), Point(1, 0)).length,
fire(grid, Point(grid.first.length, t), Point(-1, 0)).length
].max);
return 0.to(grid.first.length).fold(
ret,
(s, t) => [
s,
fire(grid, Point(t, -1), Point(0, 1)).length,
fire(grid, Point(t, grid.length), Point(0, -1)).length
].max);
}
Dad mode activated