#include #include #include #include #include #include #include #include #include #include #include #include #include using aocpp::Coord; using aocpp::Grid; namespace { auto Ski(Grid const& grid, Coord step) -> std::size_t { std::size_t const w = grid.Cols(); std::size_t const h = grid.Rows(); std::size_t trees {0}; Coord here {0,0}; while(here.y < h) { if (grid[here] == '#') trees++; here += step; while (here.x >= w) { here.x -= w; } } return trees; } auto Part1(Grid const& grid) { return Ski(grid, {3,1}); } auto Part2(Grid const& grid) { Coord const slopes[] = {{1,1}, {3,1}, {5,1}, {7,1}, {1,2}}; return std::transform_reduce( std::begin(slopes), std::end(slopes), 1ULL, std::multiplies(), [&](Coord slope) { return Ski(grid, slope); }); } } // namespace TEST_SUITE("documented examples") { std::istringstream in { "..##.......\n" "#...#...#..\n" ".#....#..#.\n" "..#.#...#.#\n" ".#...##..#.\n" "..#.##.....\n" ".#.#.#....#\n" ".#........#\n" "#.##...#...\n" "#...##....#\n" ".#..#...#.#\n" }; auto grid = Grid::Parse(in); TEST_CASE("part 1") { REQUIRE(Part1(grid) == 7); } TEST_CASE("part 2") { REQUIRE(Part2(grid) == 336); } } auto Main(std::istream & in, std::ostream & out) -> void { auto const grid {Grid::Parse(in)}; out << "Part 1: " << Part1(grid) << std::endl; out << "Part 2: " << Part2(grid) << std::endl; }