I haven't attempted this approach, but this has been on my mind a lot. I think if you keep track of all turning positions in the first run, you can run through pairs of turning positions and imagine a line extending until it hits an obstacle. I think you'd need to iterate in order of turns, and extend backwards the earlier turn in a pair, and extend forwards the later turn in the pair.
If the extended paths for two turns intercept, that is a point that an added obstacle would make a loop. I'm not 100% sure mathematically this is true, but there's less turns than there are steps, so performing the tests on turns should be faster.
Using the option 4 in the example, this is what the extended lines would look like as v
for the backwards line and <
as the forward line from the turn as noted by the +
. The x
is where these lines meet. If they don't intercept, then adding an obstacle wouldn't result in a loop forming:
....#.....
.........#
..........
..#.......
..+....#..
..v.......
.#v.......
..v.....#.
#<x<<<+...
..v...#...
I'll try to attempt this if I have time and see how it performs, but hoping someone else can check me on this and see if this is not practical.
EDIT: I attempted this and it works with the sample, but only finds about 25% of the obstacles for the real input. It's pretty tedious to debug the big map unfortunately, so I'm not sure which obstacles are being missed. I do think this is the right approach though and is so fast and elegant, if only it worked...
EDIT 2: Updated graph with better information