// Solutions to the Advent Of Code 2024. // Copyright (C) 2025 Stefan Müller // // This program is free software: you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation, either version 3 of the License, or (at your option) any later // version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . #include #include RamRun::RamRun(const size_t memorySize, const int maxBytes) : memorySize_{ memorySize }, maxBytes_{ maxBytes }, nBytes_{ 0 }, vertexReferences_{ memorySize, memorySize } { vertexReferences_.fill(getUnknownVertexReference()); } const std::string RamRun::getPuzzleName() const { return "RAM Run"; } const int RamRun::getPuzzleDay() const { return 18; } void RamRun::processDataLine(const std::string& line) { if (part2 == "") { int corrupted{ -1 }; if (!tryMarkCorrupted(line, corrupted)) { return; } if (maxBytes_ == ++nBytes_) { // 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; } } } } } void RamRun::finish() { } constexpr char RamRun::getUnknownVertexReference() { return -1; } constexpr char RamRun::getNoVertexReference() { return -2; } // 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++) { if (vertexReferences_[j][i] != getNoVertexReference()) { int v{ getVertex(graph, i, j) }; if (i != 0) { if (vertexReferences_[j][i - 1] != getNoVertexReference()) { graph.addEdge(getVertex(graph, i - 1, j), v, 1); } } if (j != 0) { if (vertexReferences_[j - 1][i] != getNoVertexReference()) { graph.addEdge(getVertex(graph, i, j - 1), v, 1); } } } } } return graph; } int RamRun::getVertex(WeightedEdgeGraph& graph, const size_t x, const size_t y) { if (vertexReferences_[y][x] == getUnknownVertexReference()) { vertexReferences_[y][x] = graph.addVertex(); } 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(); } } } }