84 lines
1.5 KiB
C++
84 lines
1.5 KiB
C++
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <tuple>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <numeric>
|
|
#include <functional>
|
|
|
|
#include <doctest.h>
|
|
|
|
#include <aocpp/Startup.hpp>
|
|
#include <aocpp/Grid.hpp>
|
|
#include <aocpp/Coord.hpp>
|
|
|
|
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;
|
|
}
|