Add solution for "Day 18: RAM Run", part 2
This commit is contained in:
@@ -35,22 +35,42 @@ const int RamRun::getPuzzleDay() const
|
||||
|
||||
void RamRun::processDataLine(const std::string& line)
|
||||
{
|
||||
if (maxBytes_ > nBytes_++)
|
||||
if (part2 == "")
|
||||
{
|
||||
std::istringstream stream{ line };
|
||||
Point2 position;
|
||||
char c;
|
||||
if (stream >> position.x >> c >> position.y)
|
||||
int corrupted{ -1 };
|
||||
if (!tryMarkCorrupted(line, corrupted))
|
||||
{
|
||||
vertexReferences_.cell(position) = getNoVertexReference();
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxBytes_ == nBytes_)
|
||||
if (maxBytes_ == ++nBytes_)
|
||||
{
|
||||
WeightedEdgeGraph graph{};
|
||||
buildGraph(graph);
|
||||
auto distances = graph.dijkstra(vertexReferences_[0][0]);
|
||||
part1 = distances[vertexReferences_[memorySize_ - 1][memorySize_ - 1]];
|
||||
// Calculates initial distances.
|
||||
auto graph = buildGraph();
|
||||
dijkstraResult_ = graph.dijkstra(vertexReferences_[0][0]);
|
||||
part1 = dijkstraResult_.distances[vertexReferences_[memorySize_ - 1][memorySize_ - 1]];
|
||||
}
|
||||
else if (maxBytes_ < nBytes_)
|
||||
{
|
||||
int pathVertex = vertexReferences_[memorySize_ - 1][memorySize_ - 1];
|
||||
while (pathVertex >= 0 && pathVertex != corrupted)
|
||||
{
|
||||
pathVertex = dijkstraResult_.predecessors[pathVertex];
|
||||
}
|
||||
if (pathVertex == corrupted)
|
||||
{
|
||||
// Calculates new paths and distances after path was interruped by corrupted position, and checks if path
|
||||
// is now blocked.
|
||||
resetVertexReferences();
|
||||
auto graph = buildGraph();
|
||||
dijkstraResult_ = graph.dijkstra(vertexReferences_[0][0]);
|
||||
if (dijkstraResult_.distances[vertexReferences_[memorySize_ - 1][memorySize_ - 1]]
|
||||
== WeightedEdgeGraph::getInfiniteDistance())
|
||||
{
|
||||
// Path is blocked.
|
||||
part2 = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,8 +89,25 @@ constexpr char RamRun::getNoVertexReference()
|
||||
return -2;
|
||||
}
|
||||
|
||||
void RamRun::buildGraph(WeightedEdgeGraph& graph)
|
||||
// Marks the position extracted from the 'line' as corrupted in the vertex reference grid.
|
||||
bool RamRun::tryMarkCorrupted(const std::string& line, int& corruptedVertex)
|
||||
{
|
||||
std::istringstream stream{ line };
|
||||
Point2 position;
|
||||
char c;
|
||||
if (stream >> position.x >> c >> position.y)
|
||||
{
|
||||
corruptedVertex = vertexReferences_.cell(position);
|
||||
vertexReferences_.cell(position) = getNoVertexReference();
|
||||
return true;
|
||||
}
|
||||
corruptedVertex = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
WeightedEdgeGraph RamRun::buildGraph()
|
||||
{
|
||||
WeightedEdgeGraph graph;
|
||||
for (size_t j = 0; j < vertexReferences_.getNRows(); j++)
|
||||
{
|
||||
for (size_t i = 0; i < vertexReferences_.getNColumns(); i++)
|
||||
@@ -95,6 +132,8 @@ void RamRun::buildGraph(WeightedEdgeGraph& graph)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
int RamRun::getVertex(WeightedEdgeGraph& graph, const size_t x, const size_t y)
|
||||
@@ -105,3 +144,17 @@ int RamRun::getVertex(WeightedEdgeGraph& graph, const size_t x, const size_t y)
|
||||
}
|
||||
return vertexReferences_[y][x];
|
||||
}
|
||||
|
||||
void RamRun::resetVertexReferences()
|
||||
{
|
||||
for (size_t j = 0; j < vertexReferences_.getNRows(); j++)
|
||||
{
|
||||
for (size_t i = 0; i < vertexReferences_.getNColumns(); i++)
|
||||
{
|
||||
if (vertexReferences_[j][i] != getNoVertexReference())
|
||||
{
|
||||
vertexReferences_[j][i] = getUnknownVertexReference();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ void ReindeerMaze::finish()
|
||||
auto exit = graph.addVertex(0);
|
||||
buildPathSegmentGraph(graph, vertexAttachedPositions, entry, exit);
|
||||
|
||||
auto shortestDistances = graph.dijkstra(exit);
|
||||
part1 = shortestDistances[entry] / 2;
|
||||
part2 = calcShortestPaths(graph, vertexAttachedPositions, entry, exit, shortestDistances);
|
||||
auto result = graph.dijkstra(exit);
|
||||
part1 = result.distances[entry] / 2;
|
||||
part2 = calcShortestPaths(graph, vertexAttachedPositions, entry, exit, result.distances);
|
||||
}
|
||||
|
||||
constexpr char ReindeerMaze::getStartChar()
|
||||
|
||||
@@ -49,13 +49,13 @@ int WeightedEdgeGraph::getEdgeWeight(const int edge) const
|
||||
return edgeWeights_[edge];
|
||||
}
|
||||
|
||||
std::vector<int> WeightedEdgeGraph::dijkstra(const int source) const
|
||||
WeightedEdgeGraph::PathsResult WeightedEdgeGraph::dijkstra(const int source) const
|
||||
{
|
||||
std::vector<int> distances(firstVertexIncidences_.size(), std::numeric_limits<int>::max());
|
||||
auto compare = [&distances](int left, int right) { return distances[left] > distances[right]; };
|
||||
PathsResult result(firstVertexIncidences_.size(), getInfiniteDistance(), -1);
|
||||
auto compare = [&result](int left, int right) { return result.distances[left] > result.distances[right]; };
|
||||
std::priority_queue<int, std::vector<int>, decltype(compare)> queue{ compare };
|
||||
|
||||
distances[source] = 0;
|
||||
result.distances[source] = 0;
|
||||
queue.push(source);
|
||||
|
||||
while (!queue.empty())
|
||||
@@ -65,16 +65,22 @@ std::vector<int> WeightedEdgeGraph::dijkstra(const int source) const
|
||||
|
||||
for (auto neighbor = begin(v); neighbor != end(); ++neighbor)
|
||||
{
|
||||
int newDistance{ distances[v] + edgeWeights_[neighbor->edge] };
|
||||
if (distances[neighbor->vertex] > newDistance)
|
||||
int newDistance{ result.distances[v] + edgeWeights_[neighbor->edge] };
|
||||
if (result.distances[neighbor->vertex] > newDistance)
|
||||
{
|
||||
distances[neighbor->vertex] = newDistance;
|
||||
result.distances[neighbor->vertex] = newDistance;
|
||||
result.predecessors[neighbor->vertex] = v;
|
||||
queue.push(neighbor->vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distances;
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr int WeightedEdgeGraph::getInfiniteDistance()
|
||||
{
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
|
||||
WeightedEdgeGraph::NeighborIterator WeightedEdgeGraph::begin(const int vertex) const
|
||||
|
||||
Reference in New Issue
Block a user