diff --git a/2022/16.cpp b/2022/16.cpp index 4cd98f4..c5f8696 100644 --- a/2022/16.cpp +++ b/2022/16.cpp @@ -34,6 +34,12 @@ namespace { namespace phx = boost::phoenix; namespace qi = boost::spirit::qi; +/// @brief The starting room as defined in the problem statement +constexpr char const* STARTING_ROOM = "AA"; + +/// @brief Arbitrary number of valves this solution supports +constexpr std::size_t MAX_VALVES = 64; + /// @brief Array of distances from one node to another. /// @tparam T distance type /// @@ -55,15 +61,14 @@ auto ShortestDistances(distance_array & dist) -> void for (auto const k : range) { for (auto const i : range) { for (auto const j : range) { - auto const new_dist = dist[i][k] + dist[k][j]; - auto & old_dist = dist[i][j]; - if (old_dist > new_dist) old_dist = new_dist; + auto const d_ikj = dist[i][k] + dist[k][j]; + auto & d_ij = dist[i][j]; + if (d_ij > d_ikj) d_ij = d_ijk; } } } } -/// @struct Room /// @brief A single record from the problem input. struct Room { /// @brief Name of the room @@ -122,7 +127,6 @@ auto FlowsFirst( ) -> std::size_t { using namespace phx::placeholders; - auto const zeros = boost::range::partition(rooms, phx::bind(&Room::flow, arg1) > 0); return std::distance(boost::begin(rooms), zeros); } @@ -134,7 +138,7 @@ auto GenerateDistances( std::vector const& rooms ) -> std::pair> { - auto const N = rooms.size(); + auto const N {rooms.size()}; // Associate the names and indexes of each room std::unordered_map names; @@ -144,15 +148,14 @@ auto GenerateDistances( distance_array distances{boost::extents[N][N]}; - // N is longer than any optimal distance by at least 1 - std::fill_n(distances.data(), distances.num_elements(), N); - for (auto const i : boost::irange(rooms.size())) { - auto & room = rooms[i]; auto di = distances[i]; + + // Default value: N is longer than any optimal distance by at least 1 + boost::range::fill(di, N); // each room is one away from adjacent rooms - for (auto const& name : room.connections) { + for (auto const& name : rooms[i].connections) { di[names[name]] = 1; } @@ -162,13 +165,12 @@ auto GenerateDistances( ShortestDistances(distances); - return {names.at("AA"), std::move(distances)}; + return {names.at(STARTING_ROOM), std::move(distances)}; } /// @brief Bitset used to track which valves have been turned on -using Valves = std::bitset<64>; +using Valves = std::bitset; -/// @struct State /// @brief Intermediate states for depth-first search in Routes struct State { /// @brief Time remaining @@ -194,11 +196,15 @@ auto Routes( distance_array const& distances ) -> std::unordered_map { + if (rooms.size() > MAX_VALVES) { + throw std::runtime_error{"Too many valves"}; + } + // Maximal flow seen at each set of open valves std::unordered_map result; // Remaining states for depth first search - std::vector states { State{initial_time, 0, start, {}} }; + std::vector states {{initial_time, 0, start, {}}}; while (!states.empty()) { auto const state = states.back(); states.pop_back(); @@ -258,7 +264,7 @@ auto Part2( { auto const routes = Routes(start, 26, rooms, distances); auto const end = routes.end(); - + std::uint64_t best {0}; for (auto it1 = routes.begin(); it1 != end; ++it1) { for (auto it2 = std::next(it1); it2 != end; ++it2) { @@ -273,7 +279,7 @@ auto Part2( } // namespace -/// @brief Print solutions to parts 1 and 2 +/// @brief Print solutions to parts 1 and 2 /// @param[in,out] in input text /// @param[in,out] out output text auto Main(std::istream & in, std::ostream & out) -> void @@ -340,4 +346,4 @@ Valve JJ has flow rate=21; tunnel leads to valve II CHECK(distances[3][2] == 1); CHECK(distances[3][3] == 0); } -} \ No newline at end of file +} diff --git a/lib/src/Startup.cpp b/lib/src/Startup.cpp index 695a640..1381fa2 100644 --- a/lib/src/Startup.cpp +++ b/lib/src/Startup.cpp @@ -53,12 +53,12 @@ namespace case 't': result.run_tests = true; break; - case ':': - std::cerr << "Missing argument to -" << char(optopt) << std::endl; - return {}; case 'h': result.print_help = true; break; + case ':': + std::cerr << "Missing argument to -" << char(optopt) << std::endl; + return {}; case '?': default: std::cerr << "Unknown flag -" << char(optopt) << std::endl;