From 0953533066b651ac356d2f833d6afdba4a354457 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 21 Dec 2021 15:28:12 +0000 Subject: [PATCH] Add 2017 Day 22 puzzles --- 2017/puzzle-22-01.cc | 95 +++++++++++++++++++++++++++++++ 2017/puzzle-22-02.cc | 133 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 2017/puzzle-22-01.cc create mode 100644 2017/puzzle-22-02.cc diff --git a/2017/puzzle-22-01.cc b/2017/puzzle-22-01.cc new file mode 100644 index 0000000..5274d49 --- /dev/null +++ b/2017/puzzle-22-01.cc @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +using Int = long; +using Coord = std::pair; + +struct State +{ + explicit State(std::vector const& initial_state) + { + Coord pos{0, 0}; + for (auto const& line : initial_state) { + pos.first = 0; + for (auto c : line) { + if (c == '#') { + infected_.insert(pos); + } + ++pos.first; + } + ++pos.second; + } + pos_ = Coord{pos.first / 2, pos.second / 2}; + } + + void burst() + { + if (infected_.contains(pos_)) { + dir_ = Coord{-dir_.second, dir_.first}; + infected_.erase(pos_); + } + else { + dir_ = Coord{dir_.second, -dir_.first}; + infected_.insert(pos_); + ++activity_; + } + pos_ = Coord{pos_.first + dir_.first, pos_.second + dir_.second}; + } + + [[nodiscard]] auto activity() const -> std::size_t { return activity_; } + + void print() const + { + Int xmin{std::numeric_limits::max()}; + Int xmax{std::numeric_limits::min()}; + Int ymin{std::numeric_limits::max()}; + Int ymax{std::numeric_limits::min()}; + for (auto const& c : infected_) { + xmin = std::min(c.first, xmin); + xmax = std::max(c.first, xmax); + ymin = std::min(c.second, ymin); + ymax = std::max(c.second, ymax); + } + + for (auto y{ymin}; y <= ymax; ++y) { + for (auto x{xmin}; x <= xmax; ++x) { + Coord pos{x, y}; + bool infected{infected_.contains(pos)}; + if (pos == pos_) { + std::cout << (infected ? '*' : '_'); + } + else { + std::cout << (infected ? '#' : '.'); + } + } + std::cout << '\n'; + } + } + +private: + std::set infected_; + Coord pos_; + Coord dir_{0, -1}; + Int activity_{0}; +}; + +auto main() -> int +{ + std::vector initial; + std::string line; + while (std::getline(std::cin, line) && !line.empty()) { + initial.push_back(line); + } + + State state(initial); + + constexpr unsigned count{10'000}; + for (unsigned i{0}; i < count; ++i) { + state.burst(); + } + + std::cout << "Number of new infections: " << state.activity() << '\n'; + return 0; +} diff --git a/2017/puzzle-22-02.cc b/2017/puzzle-22-02.cc new file mode 100644 index 0000000..f2bcab8 --- /dev/null +++ b/2017/puzzle-22-02.cc @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include + +using Int = long; +using Coord = std::pair; + +enum class InfectionState { clean, weakened, infected, flagged }; + +auto progress(InfectionState state) -> InfectionState +{ + switch (state) { + case InfectionState::clean: + return InfectionState::weakened; + case InfectionState::weakened: + return InfectionState::infected; + case InfectionState::infected: + return InfectionState::flagged; + case InfectionState::flagged: + return InfectionState::clean; + } + abort(); +} + +struct State +{ + explicit State(std::vector const& initial_state) + { + Coord pos{0, 0}; + for (auto const& line : initial_state) { + pos.first = 0; + for (auto c : line) { + if (c == '#') { + infected_.insert({pos, InfectionState::infected}); + } + ++pos.first; + } + ++pos.second; + } + pos_ = Coord{pos.first / 2, pos.second / 2}; + } + + void burst() + { + auto it{infected_.find(pos_)}; + InfectionState state{it == infected_.end() ? InfectionState::clean : it->second}; + + /* Change direction. */ + switch (state) { + case InfectionState::clean: + dir_ = Coord{dir_.second, -dir_.first}; + break; + case InfectionState::weakened: + break; + case InfectionState::infected: + dir_ = Coord{-dir_.second, dir_.first}; + break; + case InfectionState::flagged: + dir_ = Coord{-dir_.first, -dir_.second}; + break; + } + /* Update the state and record activity. */ + state = progress(state); + if (state == InfectionState::infected) { + ++activity_; + } + + /* Insert state into map. */ + if (it == infected_.end()) { + infected_.insert({pos_, state}); + } + else { + it->second = state; + } + + /* And move. */ + pos_ = Coord{pos_.first + dir_.first, pos_.second + dir_.second}; + } + + [[nodiscard]] auto activity() const -> std::size_t { return activity_; } + + void print() const + { + Int xmin{std::numeric_limits::max()}; + Int xmax{std::numeric_limits::min()}; + Int ymin{std::numeric_limits::max()}; + Int ymax{std::numeric_limits::min()}; + for (auto const& c : infected_) { + xmin = std::min(c.first.first, xmin); + xmax = std::max(c.first.first, xmax); + ymin = std::min(c.first.second, ymin); + ymax = std::max(c.first.second, ymax); + } + + for (auto y{ymin}; y <= ymax; ++y) { + for (auto x{xmin}; x <= xmax; ++x) { + Coord pos{x, y}; + auto it{infected_.find(pos)}; + auto state{it == infected_.end() ? InfectionState::clean : it->second}; + std::array cs{'_', 'w', '*', 'f', '.', 'W', '#', 'F'}; + std::cout << cs[static_cast(state) + (pos == pos_ ? 4 : 0)]; + } + std::cout << '\n'; + } + } + +private: + std::map infected_; + Coord pos_; + Coord dir_{0, -1}; + Int activity_{0}; +}; + +auto main() -> int +{ + std::vector initial; + std::string line; + while (std::getline(std::cin, line) && !line.empty()) { + initial.push_back(line); + } + + State state(initial); + + constexpr unsigned count{10'000'000}; + for (unsigned i{0}; i < count; ++i) { + state.burst(); + } + + std::cout << "Number of new infections: " << state.activity() << '\n'; + return 0; +}