diff --git a/2017/22.cpp b/2017/22.cpp new file mode 100644 index 0000000..d70bb1b --- /dev/null +++ b/2017/22.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +auto Part1(aocpp::Grid const &input) -> std::int64_t +{ + std::unordered_set infected; + + // Initialize set of infected locations + input.each([&infected](auto const pos, auto const cell) + { + if (cell == '#') + { + infected.insert(pos); + } }); + + // Start in the middle + aocpp::Coord pos; + pos.x = input.Cols() / 2; + pos.y = input.Rows() / 2; + + // Start going "up" + aocpp::Coord vel{.x = 0, .y = -1}; + + // Count the number of iterations that cause an infection + std::uint64_t infections = 0; + + for (int i = 0; i < 10'000; ++i) + { + auto const it = infected.find(pos); + if (it == end(infected)) + { + // was clean + vel = CCW(vel); // turn "left" + infected.insert(pos); // infect + infections++; + } + else + { + // was infected + vel = CW(vel); // turn "right" + infected.erase(it); // clean + } + pos += vel; // advance + } + + return infections; +} + +auto Part2(aocpp::Grid const &input) -> std::int64_t +{ + std::unordered_map cells; + + // Initialize set of infected locations + input.each([&cells](auto const pos, auto const cell) + { + if (cell == '#') + { + cells.try_emplace(pos, '#'); + } }); + + // Start in the middle + aocpp::Coord pos; + pos.x = input.Cols() / 2; + pos.y = input.Rows() / 2; + + // Start going "up" + aocpp::Coord vel{.x = 0, .y = -1}; + + // Count the number of iterations that cause an infection + std::uint64_t infections = 0; + + for (int i = 0; i < 10'000'000; ++i) + { + auto const [it, added] = cells.try_emplace(pos, 'W'); // clean becomes weakened + if (added) + { + // already inserted 'W' + vel = CCW(vel); // turn "left" + } + else + { + switch (it->second) + { + case 'W': + // no turn + it->second = '#'; + infections++; + break; + case '#': + vel = CW(vel); // turn "right" + it->second = 'F'; + break; + case 'F': + vel = Turn180(vel); + cells.erase(it); // clean + break; + default: + throw std::logic_error{"unexpected cell in steps"}; + } + } + pos += vel; // advance + } + + return infections; +} + +TEST_SUITE("2017-22 examples") +{ + TEST_CASE("part 1") + { + } + TEST_CASE("part 2") + { + } +} + +auto Main(std::istream &in, std::ostream &out) -> void +{ + auto const input = aocpp::Grid::Parse(in); + out << "Part 1: " << Part1(input) << std::endl; + out << "Part 2: " << Part2(input) << std::endl; +} diff --git a/2017/CMakeLists.txt b/2017/CMakeLists.txt index 1bee5ab..83855cc 100644 --- a/2017/CMakeLists.txt +++ b/2017/CMakeLists.txt @@ -33,3 +33,6 @@ target_link_libraries(2017_18 aocpp) add_executable(2017_19 19.cpp) target_link_libraries(2017_19 aocpp) + +add_executable(2017_22 22.cpp) +target_link_libraries(2017_22 aocpp) diff --git a/lib/include/aocpp/Coord.hpp b/lib/include/aocpp/Coord.hpp index 415668e..5e6fc7a 100644 --- a/lib/include/aocpp/Coord.hpp +++ b/lib/include/aocpp/Coord.hpp @@ -80,6 +80,7 @@ auto operator*=(Coord &, std::int64_t) -> Coord &; template<> struct std::hash { + using is_transparent = void; auto operator()(aocpp::Coord const& c) const noexcept -> std::size_t { std::hash h; return h(c.x) ^ h(c.y); diff --git a/lib/include/aocpp/Grid.hpp b/lib/include/aocpp/Grid.hpp index 5f17b77..8d09f3f 100644 --- a/lib/include/aocpp/Grid.hpp +++ b/lib/include/aocpp/Grid.hpp @@ -1,11 +1,12 @@ #ifndef AOCPP_GRID_HPP_ #define AOCPP_GRID_HPP_ +#include #include -#include -#include -#include #include +#include +#include +#include #include @@ -62,8 +63,14 @@ struct Grid { return result; } - template - auto each(F f = F{}) const { + /** + * @brief Apply the callback function across all elements of the grid. + * + * @tparam F Type of callback + * @param f Callback function + */ + template F> + auto each(F f = F{}) const -> void { auto const h = rows.size(); for (std::size_t y = 0; y < h; y++) { auto const& row = rows[y];