16
This commit is contained in:
parent
94f5cb3eb4
commit
542ccc7884
43
2022/16.cpp
43
2022/16.cpp
|
@ -31,6 +31,9 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
namespace phx = boost::phoenix;
|
||||||
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
/// @brief Array of distances from one node to another.
|
/// @brief Array of distances from one node to another.
|
||||||
/// @tparam T distance type
|
/// @tparam T distance type
|
||||||
///
|
///
|
||||||
|
@ -85,8 +88,6 @@ auto Parse(std::istream & in) -> std::vector<Room>
|
||||||
std::vector<Room> result;
|
std::vector<Room> result;
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(in, line)) {
|
while (std::getline(in, line)) {
|
||||||
namespace phx = boost::phoenix;
|
|
||||||
namespace qi = boost::spirit::qi;
|
|
||||||
using namespace qi::labels;
|
using namespace qi::labels;
|
||||||
using It = std::string::const_iterator;
|
using It = std::string::const_iterator;
|
||||||
|
|
||||||
|
@ -120,8 +121,10 @@ auto FlowsFirst(
|
||||||
std::vector<Room> & rooms
|
std::vector<Room> & rooms
|
||||||
) -> std::size_t
|
) -> std::size_t
|
||||||
{
|
{
|
||||||
auto const zeros = boost::range::partition(rooms, [](auto const& room) { return room.flow > 0; });
|
using namespace phx::placeholders;
|
||||||
return zeros - rooms.begin();
|
|
||||||
|
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
|
/// @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
|
// N is longer than any optimal distance by at least 1
|
||||||
std::fill_n(distances.data(), distances.num_elements(), N);
|
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];
|
auto di = distances[i];
|
||||||
|
|
||||||
// each room is one away from adjacent rooms
|
// 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
|
/// @return Mapping of maximum flow achievable using a particular set of valves
|
||||||
auto Routes(
|
auto Routes(
|
||||||
std::size_t const start,
|
std::size_t const start,
|
||||||
std::size_t const interesting,
|
|
||||||
std::uint64_t const initial_time,
|
std::uint64_t const initial_time,
|
||||||
std::vector<Room> const& rooms,
|
std::vector<Room> const& rooms,
|
||||||
distance_array<std::uint64_t> const& distances
|
distance_array<std::uint64_t> const& distances
|
||||||
|
@ -206,7 +209,7 @@ auto Routes(
|
||||||
|
|
||||||
auto const distances_i = distances[state.location];
|
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
|
// don't revisit a valve
|
||||||
if (state.valves.test(j)) { continue; }
|
if (state.valves.test(j)) { continue; }
|
||||||
|
|
||||||
|
@ -216,7 +219,7 @@ auto Routes(
|
||||||
if (cost >= state.time) { continue; }
|
if (cost >= state.time) { continue; }
|
||||||
|
|
||||||
auto const time = state.time - cost;
|
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;
|
auto valves = state.valves;
|
||||||
valves.set(j);
|
valves.set(j);
|
||||||
|
|
||||||
|
@ -234,33 +237,31 @@ auto Routes(
|
||||||
/// @return Maximum flow achievable
|
/// @return Maximum flow achievable
|
||||||
auto Part1(
|
auto Part1(
|
||||||
std::size_t const start,
|
std::size_t const start,
|
||||||
std::size_t const interesting,
|
|
||||||
std::vector<Room> const& rooms,
|
std::vector<Room> const& rooms,
|
||||||
distance_array<std::uint64_t> const& distances
|
distance_array<std::uint64_t> const& distances
|
||||||
) -> std::uint64_t
|
) -> 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);
|
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] start Index of the starting room
|
||||||
/// @param[in] rooms Rooms from input file
|
/// @param[in] rooms Rooms from input file
|
||||||
/// @param[in] distances Shortest distances between pairs of rooms
|
/// @param[in] distances Shortest distances between pairs of rooms
|
||||||
/// @return Maximum flow achievable
|
/// @return Maximum flow achievable
|
||||||
auto Part2(
|
auto Part2(
|
||||||
std::size_t const start,
|
std::size_t const start,
|
||||||
std::size_t const interesting,
|
|
||||||
std::vector<Room> const& rooms,
|
std::vector<Room> const& rooms,
|
||||||
distance_array<std::uint64_t> const& distances
|
distance_array<std::uint64_t> const& distances
|
||||||
) -> std::uint64_t
|
) -> 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();
|
auto const end = routes.end();
|
||||||
|
|
||||||
std::uint64_t best {0};
|
std::uint64_t best {0};
|
||||||
for (auto it1 = routes.begin(); it1 != end; std::advance(it1, 1)) {
|
for (auto it1 = routes.begin(); it1 != end; ++it1) {
|
||||||
for (auto it2 = std::next(it1); it2 != end; std::advance(it2, 1)) {
|
for (auto it2 = std::next(it1); it2 != end; ++it2) {
|
||||||
// only consider pairs that have disjoint sets of valves
|
// only consider pairs that have disjoint sets of valves
|
||||||
if ((it1->first & it2->first).none()) {
|
if ((it1->first & it2->first).none()) {
|
||||||
best = std::max(best, it1->second + it2->second);
|
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
|
Valve JJ has flow rate=21; tunnel leads to valve II
|
||||||
)"};
|
)"};
|
||||||
auto rooms = Parse(in);
|
auto rooms = Parse(in);
|
||||||
auto const interesting = FlowsFirst(rooms);
|
auto const n = FlowsFirst(rooms);
|
||||||
auto const [start, distances] = GenerateDistances(rooms);
|
auto const [start, distances] = GenerateDistances(rooms);
|
||||||
CHECK(1651 == Part1(start, interesting, rooms, distances));
|
rooms.resize(n);
|
||||||
CHECK(1707 == Part2(start, interesting, rooms, distances));
|
CHECK(1651 == Part1(start, rooms, distances));
|
||||||
|
CHECK(1707 == Part2(start, rooms, distances));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("shortest path") {
|
TEST_CASE("shortest path") {
|
||||||
|
@ -339,6 +341,7 @@ auto main(int argc, char** argv) -> int
|
||||||
auto rooms = Parse(*aocpp::Startup(argc, argv));
|
auto rooms = Parse(*aocpp::Startup(argc, argv));
|
||||||
auto const n = FlowsFirst(rooms);
|
auto const n = FlowsFirst(rooms);
|
||||||
auto const [start, distances] = GenerateDistances(rooms);
|
auto const [start, distances] = GenerateDistances(rooms);
|
||||||
std::cout << "Part 1: " << Part1(start, n, rooms, distances) << std::endl;
|
rooms.resize(n);
|
||||||
std::cout << "Part 2: " << Part2(start, n, rooms, distances) << std::endl;
|
std::cout << "Part 1: " << Part1(start, rooms, distances) << std::endl;
|
||||||
|
std::cout << "Part 2: " << Part2(start, rooms, distances) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user