diff --git a/2022/16.cpp b/2022/16.cpp index 70d8ec1..408a48d 100644 --- a/2022/16.cpp +++ b/2022/16.cpp @@ -31,6 +31,9 @@ namespace { +namespace phx = boost::phoenix; +namespace qi = boost::spirit::qi; + /// @brief Array of distances from one node to another. /// @tparam T distance type /// @@ -85,8 +88,6 @@ auto Parse(std::istream & in) -> std::vector std::vector result; std::string line; while (std::getline(in, line)) { - namespace phx = boost::phoenix; - namespace qi = boost::spirit::qi; using namespace qi::labels; using It = std::string::const_iterator; @@ -120,8 +121,10 @@ auto FlowsFirst( std::vector & rooms ) -> std::size_t { - auto const zeros = boost::range::partition(rooms, [](auto const& room) { return room.flow > 0; }); - return zeros - rooms.begin(); + using namespace phx::placeholders; + + auto const zeros = boost::range::partition(rooms, phx::bind(&Room::flow, arg1) > 0); + return std::distance(boost::begin(rooms), zeros); } /// @brief Computes the distances between rooms and finds the address of the starting room @@ -144,7 +147,8 @@ auto GenerateDistances( // N is longer than any optimal distance by at least 1 std::fill_n(distances.data(), distances.num_elements(), N); - for (auto [i, room] : rooms | boost::adaptors::indexed()) { + for (auto const i : boost::irange(rooms.size())) { + auto & room = rooms[i]; auto di = distances[i]; // each room is one away from adjacent rooms @@ -185,7 +189,6 @@ struct State { /// @return Mapping of maximum flow achievable using a particular set of valves auto Routes( std::size_t const start, - std::size_t const interesting, std::uint64_t const initial_time, std::vector const& rooms, distance_array const& distances @@ -206,7 +209,7 @@ auto Routes( auto const distances_i = distances[state.location]; - for (auto const j : boost::irange(interesting)) { + for (auto const [j, room] : rooms | boost::adaptors::indexed()) { // don't revisit a valve if (state.valves.test(j)) { continue; } @@ -216,7 +219,7 @@ auto Routes( if (cost >= state.time) { continue; } auto const time = state.time - cost; - auto const flow = state.flow + rooms[j].flow * time; + auto const flow = state.flow + room.flow * time; auto valves = state.valves; valves.set(j); @@ -234,33 +237,31 @@ auto Routes( /// @return Maximum flow achievable auto Part1( std::size_t const start, - std::size_t const interesting, std::vector const& rooms, distance_array const& distances ) -> std::uint64_t { - auto const routes = Routes(start, interesting, 30, rooms, distances); + auto const routes = Routes(start, 30, rooms, distances); return *boost::range::max_element(routes | boost::adaptors::map_values); } -/// @brief Maximize the water flow using two actos and 26 minutes +/// @brief Maximize the water flow using two actors and 26 minutes /// @param[in] start Index of the starting room /// @param[in] rooms Rooms from input file /// @param[in] distances Shortest distances between pairs of rooms /// @return Maximum flow achievable auto Part2( std::size_t const start, - std::size_t const interesting, std::vector const& rooms, distance_array const& distances ) -> std::uint64_t { - auto const routes = Routes(start, interesting, 26, rooms, distances); + 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; std::advance(it1, 1)) { - for (auto it2 = std::next(it1); it2 != end; std::advance(it2, 1)) { + for (auto it1 = routes.begin(); it1 != end; ++it1) { + for (auto it2 = std::next(it1); it2 != end; ++it2) { // only consider pairs that have disjoint sets of valves if ((it1->first & it2->first).none()) { best = std::max(best, it1->second + it2->second); @@ -287,10 +288,11 @@ Valve II has flow rate=0; tunnels lead to valves AA, JJ Valve JJ has flow rate=21; tunnel leads to valve II )"}; auto rooms = Parse(in); - auto const interesting = FlowsFirst(rooms); + auto const n = FlowsFirst(rooms); auto const [start, distances] = GenerateDistances(rooms); - CHECK(1651 == Part1(start, interesting, rooms, distances)); - CHECK(1707 == Part2(start, interesting, rooms, distances)); + rooms.resize(n); + CHECK(1651 == Part1(start, rooms, distances)); + CHECK(1707 == Part2(start, rooms, distances)); } TEST_CASE("shortest path") { @@ -339,6 +341,7 @@ auto main(int argc, char** argv) -> int auto rooms = Parse(*aocpp::Startup(argc, argv)); auto const n = FlowsFirst(rooms); auto const [start, distances] = GenerateDistances(rooms); - std::cout << "Part 1: " << Part1(start, n, rooms, distances) << std::endl; - std::cout << "Part 2: " << Part2(start, n, rooms, distances) << std::endl; + rooms.resize(n); + std::cout << "Part 1: " << Part1(start, rooms, distances) << std::endl; + std::cout << "Part 2: " << Part2(start, rooms, distances) << std::endl; }