It's the weekend for me now. 12/17 specifically. Oh jeez Christmas is close. I just woke up, and I'm going to try for two or three of these today. But from what I recall from last year (as well as yesterday) this is when it starts really ramping up. And based on the curve of completions it's the point where significantly less people are finishing each day. Let's hope I can keep this up... or at least I have the motivation to finish.
Okay, this one is a pretty neat take on a pathfinding algorithm. You can only go uphill one elevation per step, but you can go downhill as much as you need to in one step. I can actually make out a bit of the structure of the hill from the input, it looks pretty neat.
I think I may do a sort of breadth-first search? But I know the path is winding, possibly VERY winding, so I'm going to have a sort of priority queue, where I start searching from the shortest path. I think there was a name for this? Bah. I don't need to keep track of the actual path, I don't think, just the length. If I keep a set of visited coordinates, I can basically keep searching out without recording.
vector<string> map;
set<pair<int, int>> visited;
pair<int, int> end;
priority_queue<PathPoint, vector<PathPoint>, PathComparitor> queue;
/// Parsing code...
auto canClimb = [&](int x, int y, char c)
{
if (x < 0 || x >= map.size()) return false;
if (y < 0 || y >= map[0].size()) return false;
if (visited.find(pair<int, int>(x, y)) != visited.end()) return false;
if (c == 'S') c = 'a';
if (c == 'E') c = 'z';
char t = map[x][y] == 'E' ? 'z' : map[x][y];
return (t - c) <= UP_LIMIT;
};
while (queue.size() > 0)
{
PathPoint p = queue.top(); queue.pop();
if (pair<int, int>(p.x, p.y) == end)
{
cout << "Path length: " << p.length;
return 0;
}
// Test down
if (canClimb(p.x+1, p.y, map[p.x][p.y]))
{
visited.insert(pair<int, int>(p.x+1, p.y));
queue.push(PathPoint(p.x+1, p.y, p.length+1));
}
/// Test other directions...
}
Interesting, now I need to find the shortest path from any trail starting with 'a'. This should be simple enough though... just another loop that will start from every 'a' position, instead of just 'S'.
// Find starts
for (int i = 0; i < line.length(); i++)
if (line[i] == 'S' || line[i] == 'a')
starts.push_back(pair<int, int>(row, i));
Add another loop to go through all of those instead of just the first... and it works! It takes a minute, since there's over 600 possible starting points, but I got a pretty decent path length!