aocpp/2022/12.cpp

86 lines
2.0 KiB
C++
Raw Normal View History

2023-01-18 15:24:18 -08:00
#include <cstdint>
#include <iostream>
2023-03-22 14:02:29 -07:00
#include <optional>
2023-01-18 15:24:18 -08:00
#include <set>
#include <sstream>
#include <tuple>
#include <vector>
#include <doctest.h>
#include <aocpp/Coord.hpp>
#include <aocpp/Grid.hpp>
#include <aocpp/Startup.hpp>
using aocpp::Coord;
using aocpp::Grid;
namespace {
2023-03-22 14:02:29 -07:00
auto Parse(std::istream & in) -> std::tuple<Coord, std::vector<Coord>, Coord, Grid>
2023-01-18 15:24:18 -08:00
{
2023-03-22 14:02:29 -07:00
Coord start1 {};
std::vector<Coord> starts2;
2023-01-18 15:24:18 -08:00
Coord end {};
auto grid = Grid::Parse(in);
grid.each([&](Coord c, char v) {
switch (v) {
2023-03-22 14:02:29 -07:00
case 'S': grid[c] = 'a'; start1 = c; break;
2023-01-18 15:24:18 -08:00
case 'E': grid[c] = 'z'; end = c; break;
2023-03-22 14:02:29 -07:00
case 'a': starts2.push_back(c); break;
2023-01-18 15:24:18 -08:00
}
});
2023-03-22 14:02:29 -07:00
return {start1, std::move(starts2), end, std::move(grid)};
2023-01-18 15:24:18 -08:00
}
2023-03-22 14:02:29 -07:00
auto Solve(std::vector<Coord> starts, Coord end, Grid const& grid) -> std::optional<std::int64_t>
2023-01-18 15:24:18 -08:00
{
std::vector<Coord> next_layer;
std::set<Coord> seen;
std::int64_t counter {1};
2023-03-22 14:02:29 -07:00
while (!starts.empty()) {
for (auto here : starts) {
2023-01-18 15:24:18 -08:00
if (!seen.insert(here).second) continue;
auto here_height = grid[here];
for (auto next : {Up(here), Down(here), Left(here), Right(here)}) {
if (!grid.contains(next)) continue;
2023-03-22 14:02:29 -07:00
if (grid[next] - 1 > here_height) continue;
2023-01-18 15:24:18 -08:00
if (next == end) { return counter; }
next_layer.push_back(next);
}
}
counter++;
2023-03-22 14:02:29 -07:00
starts.clear();
std::swap(starts, next_layer);
2023-01-18 15:24:18 -08:00
}
2023-03-22 14:02:29 -07:00
return {};
2023-01-18 15:24:18 -08:00
}
} // namespace
TEST_SUITE("2022-12 examples") {
TEST_CASE("documented example") {
std::istringstream in {
"Sabqponm\n"
"abcryxxl\n"
"accszExk\n"
"acctuvwj\n"
"abdefghi\n"
};
2023-03-22 14:02:29 -07:00
auto [start1, starts2, end, grid] = Parse(in);
CHECK(31 == Solve({start1}, end, grid));
CHECK(29 == Solve(std::move(starts2), end, grid));
2023-01-18 15:24:18 -08:00
}
}
2023-01-31 09:15:15 -08:00
auto Main(std::istream & in, std::ostream & out) -> void
2023-01-18 15:24:18 -08:00
{
2023-03-22 14:02:29 -07:00
auto [start1, starts2, end, grid] = Parse(in);
out << "Part 1: " << Solve({start1}, end, grid).value_or(-1) << std::endl;
out << "Part 2: " << Solve(std::move(starts2), end, grid).value_or(-1) << std::endl;
2023-01-18 15:24:18 -08:00
}