extract generator code into library

This commit is contained in:
2023-04-02 15:30:34 -07:00
parent 4d884d7b1c
commit 9b4c881903
2 changed files with 80 additions and 43 deletions

View File

@@ -1,5 +1,6 @@
#include <version>
#include <concepts>
#include <cstdint>
#include <iostream>
#include <set>
@@ -7,14 +8,6 @@
#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>
@@ -23,6 +16,7 @@ namespace co = std::experimental;
#include <aocpp/Startup.hpp>
#include <aocpp/Coord.hpp>
#include <aocpp/Generator.hpp>
namespace {
@@ -103,35 +97,7 @@ 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
auto SearchOrder(std::set<aocpp::Coord> & world, aocpp::Coord here) -> aocpp::Generator<aocpp::Coord>
{
co_yield aocpp::Down(here);
co_yield aocpp::Left(aocpp::Down(here));
@@ -143,15 +109,15 @@ auto Part1(std::int64_t bottom, std::set<aocpp::Coord> world) -> std::size_t
{
auto const starting_size = world.size();
auto path = std::vector<CoordGenerator>{};
auto path = std::vector<aocpp::Generator<aocpp::Coord>>{};
path.reserve(bottom - TOP.y);
path.push_back(SearchOrder(world, TOP));
while (!path.empty()) {
if (auto next = path.back().next()) {
if (auto next = path.back()()) {
if (!world.contains(*next)) {
if (next->y == bottom) {
break;
return world.size() - starting_size;
}
path.push_back(SearchOrder(world, *next));
}
@@ -160,19 +126,19 @@ auto Part1(std::int64_t bottom, std::set<aocpp::Coord> world) -> std::size_t
}
}
return world.size() - starting_size;
throw std::runtime_error{"No solution for part 1"};
}
auto Part2(std::int64_t bottom, std::set<aocpp::Coord> world) -> std::size_t
{
auto const starting_size = world.size();
auto path = std::vector<CoordGenerator>{};
auto path = std::vector<aocpp::Generator<aocpp::Coord>>{};
path.reserve(2 + bottom - TOP.y);
path.push_back(SearchOrder(world, TOP));
while (!path.empty()) {
if (auto next = path.back().next()) {
if (auto next = path.back()()) {
if (next->y - 2 != bottom && !world.contains(*next)) {
path.push_back(SearchOrder(world, *next));
}