From 495222c63c18edde04240edeeedb4962fc3332b7 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Mon, 20 Dec 2021 07:46:43 +0000 Subject: [PATCH] Add 2021 day 20 puzzles --- 2021/puzzle-20-01.cc | 104 ++++++++++++++++++++++++++++++++++++++++++ 2021/puzzle-20-02.cc | 106 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 2021/puzzle-20-01.cc create mode 100644 2021/puzzle-20-02.cc diff --git a/2021/puzzle-20-01.cc b/2021/puzzle-20-01.cc new file mode 100644 index 0000000..7bdcfdf --- /dev/null +++ b/2021/puzzle-20-01.cc @@ -0,0 +1,104 @@ +#include +#include +#include + +struct State +{ + explicit State(std::string const& rules) : rules_(rules) + { + assert(rules.size() == 512); + assert(rules[0] == '.' || rules[511] == '.'); + } + + void add_row(std::string const& row) + { + using namespace std::string_literals; + lights_.push_back(row); + } + + auto size() const noexcept -> std::size_t + { + std::size_t result{0}; + for (auto const& row : lights_) { + result += std::count(row.begin(), row.end(), '#'); + } + return result; + } + + auto next() const -> State + { + std::ptrdiff_t longest_line( + std::max_element(lights_.begin(), lights_.end(), [](auto const& l, auto const& r) { + return l.size() < r.size(); + })->size()); + State result{rules_}; + if (rules_[0] == '#') { + result.outside_set_ = !outside_set_; + } + std::ptrdiff_t row_count(lights_.size()); + for (std::ptrdiff_t y{-1}; y <= row_count; ++y) { + std::string next_row; + next_row.reserve(longest_line); + for (std::ptrdiff_t x{-1}; x <= longest_line; ++x) { + next_row.push_back(lit(x, y) ? '#' : '.'); + } + result.add_row(next_row); + } + return result; + } + + [[nodiscard]] auto lit(std::ptrdiff_t x0, std::ptrdiff_t y0) const noexcept -> bool + { + auto num{0}; + for (auto y{y0 - 1}; y < y0 + 2; ++y) { + for (auto x{x0 - 1}; x < x0 + 2; ++x) { + num <<= 1; + num |= bit_set(x, y); + } + } + return rules_[num] == '#'; + } + + void print(std::ostream& os) const + { + for (auto const& row : lights_) { + os << row << '\n'; + } + } + +private: + auto bit_set(std::ptrdiff_t x, std::ptrdiff_t y) const noexcept -> bool + { + if (y < 0 || y >= lights_.size()) { + return outside_set_; + } + if (x < 0 || x >= lights_[y].size()) { + return outside_set_; + } + return lights_[y][x] == '#'; + } + + std::string rules_; + std::vector lights_; + bool outside_set_{false}; +}; + +auto main() -> int +{ + std::string line; + if (!std::getline(std::cin, line)) { + std::cerr << "Unable to read rules.\n"; + return 1; + } + State state{line}; + std::getline(std::cin, line); + assert(line.empty()); + while (std::getline(std::cin, line) && !line.empty()) { + state.add_row(line); + } + + state = state.next(); + state = state.next(); + + std::cout << "Number lit: " << state.size() << '\n'; +} diff --git a/2021/puzzle-20-02.cc b/2021/puzzle-20-02.cc new file mode 100644 index 0000000..fe3456b --- /dev/null +++ b/2021/puzzle-20-02.cc @@ -0,0 +1,106 @@ +#include +#include +#include + +struct State +{ + explicit State(std::string const& rules) : rules_(rules) + { + assert(rules.size() == 512); + assert(rules[0] == '.' || rules[511] == '.'); + } + + void add_row(std::string const& row) + { + using namespace std::string_literals; + lights_.push_back(row); + } + + auto size() const noexcept -> std::size_t + { + std::size_t result{0}; + for (auto const& row : lights_) { + result += std::count(row.begin(), row.end(), '#'); + } + return result; + } + + auto next() const -> State + { + std::ptrdiff_t longest_line( + std::max_element(lights_.begin(), lights_.end(), [](auto const& l, auto const& r) { + return l.size() < r.size(); + })->size()); + State result{rules_}; + if (rules_[0] == '#') { + result.outside_set_ = !outside_set_; + } + std::ptrdiff_t row_count(lights_.size()); + for (std::ptrdiff_t y{-1}; y <= row_count; ++y) { + std::string next_row; + next_row.reserve(longest_line); + for (std::ptrdiff_t x{-1}; x <= longest_line; ++x) { + next_row.push_back(lit(x, y) ? '#' : '.'); + } + result.add_row(next_row); + } + return result; + } + + [[nodiscard]] auto lit(std::ptrdiff_t x0, std::ptrdiff_t y0) const noexcept -> bool + { + auto num{0}; + for (auto y{y0 - 1}; y < y0 + 2; ++y) { + for (auto x{x0 - 1}; x < x0 + 2; ++x) { + num <<= 1; + num |= bit_set(x, y); + } + } + return rules_[num] == '#'; + } + + void print(std::ostream& os) const + { + for (auto const& row : lights_) { + os << row << '\n'; + } + } + +private: + auto bit_set(std::ptrdiff_t x, std::ptrdiff_t y) const noexcept -> bool + { + if (y < 0 || y >= lights_.size()) { + return outside_set_; + } + if (x < 0 || x >= lights_[y].size()) { + return outside_set_; + } + return lights_[y][x] == '#'; + } + + std::string rules_; + std::vector lights_; + bool outside_set_{false}; +}; + +auto main() -> int +{ + std::string line; + if (!std::getline(std::cin, line)) { + std::cerr << "Unable to read rules.\n"; + return 1; + } + State state{line}; + std::getline(std::cin, line); + assert(line.empty()); + while (std::getline(std::cin, line) && !line.empty()) { + state.add_row(line); + } + + constexpr unsigned count{50}; + for (unsigned i{0}; i < count; ++i) { + state = state.next(); + } + + std::cout << "Number lit: " << state.size() << '\n'; +}