diff --git a/2020/02.cpp b/2020/02.cpp new file mode 100644 index 0000000..a2d5c75 --- /dev/null +++ b/2020/02.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace { + +using Entry = std::tuple; + +auto Parse(std::string const& str) -> Entry +{ + std::size_t lo, hi, n; + char letter; + auto res = std::sscanf(str.c_str(), "%zu-%zu %c: %zn", &lo, &hi, &letter, &n); + if (res != 3) { throw std::runtime_error{"bad input"}; } + return {lo, hi, letter, str.substr(n)}; +} + +auto Part1(Entry const& entry) -> bool { + auto const& [lo, hi, letter, text] = entry; + auto n = std::count(text.begin(), text.end(), letter); + return lo <= n && n <= hi; +} + +auto Part2(Entry const& entry) -> bool +{ + auto const& [lo, hi, letter, text] = entry; + return (text.at(lo-1) == letter) != (text.at(hi-1) == letter); +} + +} // namespace + +TEST_SUITE("documented examples") { + +TEST_CASE("parser") { + REQUIRE(Parse("1-3 z: example") == Entry{1,3,'z',"example"}); +} + +TEST_CASE("part 1") { + REQUIRE( Part1(Parse("1-3 a: abcde"))); + REQUIRE(!Part1(Parse("1-3 b: cdefg"))); + REQUIRE( Part1(Parse("2-9 c: ccccccccc"))); +} + +TEST_CASE("part 2") { + REQUIRE( Part2(Parse("1-3 a: abcde"))); + REQUIRE(!Part2(Parse("1-3 b: cdefg"))); + REQUIRE(!Part2(Parse("2-9 c: ccccccccc"))); +} + +} + +auto main(int argc, char** argv) -> int { + auto & in = aocpp::Startup(argc, argv); + std::uint64_t part1{}, part2{}; + + std::string line; + while (std::getline(in, line)) { + auto entry = Parse(line); + if (Part1(entry)) part1++; + if (Part2(entry)) part2++; + } + std::cout << "Part 1: " << part1 << std::endl; + std::cout << "Part 2: " << part2 << std::endl; +} diff --git a/2020/03.cpp b/2020/03.cpp new file mode 100644 index 0000000..d283873 --- /dev/null +++ b/2020/03.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +using aocpp::Startup; +using aocpp::Coord; +using aocpp::Grid; + +namespace { + +auto Ski(Grid const& grid, Coord step) -> std::size_t +{ + std::size_t const w = grid.rows[0].size(); + std::size_t trees {0}; + Coord here {0,0}; + + while(here.y < grid.rows.size()) { + 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(int argc, char** argv) -> int { + auto grid = Grid::Parse(Startup(argc, argv)); + std::cout << "Part 1: " << Part1(grid) << std::endl; + std::cout << "Part 2: " << Part2(grid) << std::endl; +} diff --git a/2020/CMakeLists.txt b/2020/CMakeLists.txt index 93f0586..697d576 100644 --- a/2020/CMakeLists.txt +++ b/2020/CMakeLists.txt @@ -1,2 +1,5 @@ -add_executable(2020_01 01.cpp) -target_link_libraries(2020_01 aocpp) +add_executable(2020_02 02.cpp) +target_link_libraries(2020_02 aocpp) + +add_executable(2020_03 03.cpp) +target_link_libraries(2020_03 aocpp) \ No newline at end of file