What is the optimal algorithm for Part 2?
What is the optimal algorithm for Part 2?
I know that we can brute force it by placing an obstacle at every valid position in the path, but is there a more elegant / efficient solution?
What is the optimal algorithm for Part 2?
I know that we can brute force it by placing an obstacle at every valid position in the path, but is there a more elegant / efficient solution?
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
That's a neat idea, but isn't it possible that adding an obstacle could send the guard into a loop in a previously unexplored part of the map? I think you'd miss that case.
I'm not sure I understand the concern, maybe a visualization would help describe what you're talking about? I updated my comment to describe my process in better detail, it was confusing before. I'm only focused in checking unobstructed straight lines from places where the guard has turned, so I don't think it could get into unexplored areas.
You gave me an idea!
(ID, direction)
to (next ID, direction)
(if any) -- that is, for each obstacle, update the map entry for any preceding obstacle that could reach it.I think this would give a pretty good speed up, and you might not need to worry about only checking intersections.
One optimization some used was to detect loops by only recording the turning points instead of all walked tiles.
I'm also struggling with part 2. At the moment I am following the path and in each place I look if can connect with an earlier part of the path to the right by placing an obstacle, but without cutting off another earlier part of the path with that obstacle. I have indexes for each path location to see where in the path they first appear.
However at the moment I still have a bug counting too many possibilities. Any other ideas?
I am using same solution, and getting right count with test input, but the actual input gives too many.
Annoying, and really hard to debug. I made renderer to visualize, but unable to find the bug.
One misunderstanding was that I counted same walls twice, because the result should not count same added wall twice if it has same x,y.
Yeah something like that happend for me too, and later I counted too little because it would not recognise some possible solutions. Finally I solved it by just walking along the path and at each location put an obstacle in front of it and then check if the changed map results in a path enters longer than 10000 steps. Not pretty but at least it lead to the right result with a runtime of ~3 seconds. I would have saved a lot of time if I had tried the "brute force" way before, so I guess lesson learned.