mess with some coroutines
This commit is contained in:
parent
ffbb5c9fb2
commit
4d884d7b1c
89
2022/14.cpp
89
2022/14.cpp
|
@ -1,9 +1,20 @@
|
|||
#include <version>
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#if __has_include(<coroutine>)
|
||||
#include <coroutine>
|
||||
namespace co = std;
|
||||
#elif __has_include(<experimental/coroutine>)
|
||||
#include <experimental/coroutine>
|
||||
namespace co = std::experimental;
|
||||
#endif
|
||||
|
||||
#include <boost/phoenix.hpp>
|
||||
#include <boost/range/irange.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
@ -92,23 +103,59 @@ auto FindBottom(Input const& input) -> std::int64_t
|
|||
return result;
|
||||
}
|
||||
|
||||
struct CoordPromise;
|
||||
|
||||
struct CoordGenerator : co::coroutine_handle<CoordPromise> {
|
||||
using promise_type = struct CoordPromise;
|
||||
auto next() -> std::optional<aocpp::Coord>;
|
||||
};
|
||||
|
||||
struct CoordPromise {
|
||||
std::optional<aocpp::Coord> output;
|
||||
std::exception_ptr e;
|
||||
|
||||
auto get_return_object() -> CoordGenerator { return { CoordGenerator::from_promise(*this)}; }
|
||||
auto initial_suspend() noexcept -> co::suspend_always { return {}; }
|
||||
auto final_suspend() noexcept -> co::suspend_never { return {}; }
|
||||
auto return_void() { output.reset(); }
|
||||
auto yield_value(aocpp::Coord coord) -> co::suspend_always { output = coord; return {}; }
|
||||
auto unhandled_exception() -> void { e = std::current_exception(); }
|
||||
};
|
||||
|
||||
auto CoordGenerator::next() -> std::optional<aocpp::Coord> {
|
||||
resume();
|
||||
auto & p = promise();
|
||||
if (p.e) {
|
||||
std::rethrow_exception(p.e);
|
||||
}
|
||||
return p.output;
|
||||
}
|
||||
|
||||
auto SearchOrder(std::set<aocpp::Coord> & world, aocpp::Coord here) -> CoordGenerator
|
||||
{
|
||||
co_yield aocpp::Down(here);
|
||||
co_yield aocpp::Left(aocpp::Down(here));
|
||||
co_yield aocpp::Right(aocpp::Down(here));
|
||||
world.insert(here);
|
||||
}
|
||||
|
||||
auto Part1(std::int64_t bottom, std::set<aocpp::Coord> world) -> std::size_t
|
||||
{
|
||||
auto path = std::vector<aocpp::Coord>{TOP};
|
||||
auto const starting_size = world.size();
|
||||
|
||||
auto path = std::vector<CoordGenerator>{};
|
||||
path.reserve(bottom - TOP.y);
|
||||
path.push_back(SearchOrder(world, TOP));
|
||||
|
||||
while (!path.empty()) {
|
||||
auto & here = path.back();
|
||||
if (here.y == bottom) {
|
||||
return world.size() - starting_size;
|
||||
} else if (!world.contains(aocpp::Down(here))) {
|
||||
path.push_back(aocpp::Down(here));
|
||||
} else if (!world.contains(aocpp::Left(aocpp::Down(here)))) {
|
||||
path.push_back(aocpp::Left(aocpp::Down(here)));
|
||||
} else if (!world.contains(aocpp::Right(aocpp::Down(here)))) {
|
||||
path.push_back(aocpp::Right(aocpp::Down(here)));
|
||||
if (auto next = path.back().next()) {
|
||||
if (!world.contains(*next)) {
|
||||
if (next->y == bottom) {
|
||||
break;
|
||||
}
|
||||
path.push_back(SearchOrder(world, *next));
|
||||
}
|
||||
} else {
|
||||
world.insert(here);
|
||||
path.pop_back();
|
||||
}
|
||||
}
|
||||
|
@ -118,22 +165,18 @@ auto Part1(std::int64_t bottom, std::set<aocpp::Coord> world) -> std::size_t
|
|||
|
||||
auto Part2(std::int64_t bottom, std::set<aocpp::Coord> world) -> std::size_t
|
||||
{
|
||||
auto path = std::vector<aocpp::Coord>{TOP};
|
||||
auto const starting_size = world.size();
|
||||
|
||||
auto path = std::vector<CoordGenerator>{};
|
||||
path.reserve(2 + bottom - TOP.y);
|
||||
path.push_back(SearchOrder(world, TOP));
|
||||
|
||||
while (!path.empty()) {
|
||||
auto & here = path.back();
|
||||
if (here.y == 1 + bottom) {
|
||||
world.insert(here);
|
||||
path.pop_back();
|
||||
} else if (!world.contains(aocpp::Down(here))) {
|
||||
path.push_back(aocpp::Down(here));
|
||||
} else if (!world.contains(aocpp::Left(aocpp::Down(here)))) {
|
||||
path.push_back(aocpp::Left(aocpp::Down(here)));
|
||||
} else if (!world.contains(aocpp::Right(aocpp::Down(here)))) {
|
||||
path.push_back(aocpp::Right(aocpp::Down(here)));
|
||||
if (auto next = path.back().next()) {
|
||||
if (next->y - 2 != bottom && !world.contains(*next)) {
|
||||
path.push_back(SearchOrder(world, *next));
|
||||
}
|
||||
} else {
|
||||
world.insert(here);
|
||||
path.pop_back();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user