From d3622ff806436bcfebb1e5da68e9a9c3d8a151dd Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 7 Dec 2021 16:09:20 +0000 Subject: [PATCH] Add 2016 day 20 puzzles --- 2016/puzzle-20-01.cc | 87 +++++++++++++++++++++++++++++++++++++ 2016/puzzle-20-02.cc | 101 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 2016/puzzle-20-01.cc create mode 100644 2016/puzzle-20-02.cc diff --git a/2016/puzzle-20-01.cc b/2016/puzzle-20-01.cc new file mode 100644 index 0000000..0e6afc0 --- /dev/null +++ b/2016/puzzle-20-01.cc @@ -0,0 +1,87 @@ +#include +#include +#include + +struct Ranges +{ + void add(std::uint32_t low, std::uint32_t high) + { + static constexpr auto max{std::numeric_limits::max()}; + auto it{ranges_.begin()}; + while (it != ranges_.end()) { + if (low != 0 && it->second < low - 1) { + ++it; + } + else if (high == max || high + 1 < it->first) { + ranges_.insert(it, {low, high}); + return; + } + else { + it->first = std::min(low, it->first); + it->second = std::max(high, it->second); + auto it2{it + 1}; + while (it2 != ranges_.end() && (it->second == std::numeric_limits::max() || + it2->first <= it->second + 1)) { + it->second = it2->second; + ++it2; + } + ranges_.erase(it + 1, it2); + return; + } + } + + ranges_.push_back({low, high}); + } + + Ranges inverse() const + { + Ranges result; + auto it{ranges_.begin()}; + if (it == ranges_.end()) { + result.ranges_.push_back({0, std::numeric_limits::max()}); + return result; + } + if (it->first != 0) { + result.ranges_.push_back({0, it->first - 1}); + } + auto low{it->second + 1}; + while (it != ranges_.end()) { + result.ranges_.push_back({low, it->first - 1}); + low = it->second + 1; + ++it; + } + if (low != 0) { + result.ranges_.push_back({low, std::numeric_limits::max()}); + } + return result; + } + + auto lowest() const -> std::uint32_t + { + if (ranges_.empty()) { + return std::numeric_limits::max(); + } + return ranges_.front().first; + } + +private: + std::vector> ranges_; +}; + +auto main() -> int +{ + static std::regex match_re{"(\\d+)-(\\d+)"}; + std::string line; + std::smatch m; + Ranges ranges; + while (std::getline(std::cin, line)) { + if (!std::regex_search(line, m, match_re)) { + std::cerr << "Unable to match: " << line << '\n'; + return 1; + } + ranges.add(std::stoul(m.str(1)), std::stoul(m.str(2))); + } + + std::cout << "First available IP address: " << ranges.inverse().lowest() << '\n'; + return 0; +} \ No newline at end of file diff --git a/2016/puzzle-20-02.cc b/2016/puzzle-20-02.cc new file mode 100644 index 0000000..7eb7ca5 --- /dev/null +++ b/2016/puzzle-20-02.cc @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +struct Ranges +{ + auto operator==(Ranges const& rhs) const noexcept { return ranges_ == rhs.ranges_; } + + void add(std::uint32_t low, std::uint32_t high) + { + static constexpr auto max{std::numeric_limits::max()}; + auto it{ranges_.begin()}; + while (it != ranges_.end()) { + if (low != 0 && it->second < low - 1) { + ++it; + } + else if (high == max || high + 1 < it->first) { + ranges_.insert(it, {low, high}); + return; + } + else { + it->first = std::min(low, it->first); + it->second = std::max(high, it->second); + auto it2{it + 1}; + while (it2 != ranges_.end() && (it->second == std::numeric_limits::max() || + it2->first <= it->second + 1)) { + it->second = std::max(it->second, it2->second); + ++it2; + } + ranges_.erase(it + 1, it2); + return; + } + } + + ranges_.emplace_back(low, high); + } + + [[nodiscard]] auto inverse() const -> Ranges + { + Ranges result; + auto it{ranges_.begin()}; + assert(it->first <= it->second); + if (it == ranges_.end()) { + result.ranges_.emplace_back(0, std::numeric_limits::max()); + return result; + } + if (it->first != 0) { + result.ranges_.emplace_back(0, it->first - 1); + } + auto low{it->second + 1}; + for (++it; it != ranges_.end(); ++it) { + assert(low < it->first); + assert(it->first <= it->second); + result.ranges_.emplace_back(low, it->first - 1); + low = it->second + 1; + } + if (low != 0) { + result.ranges_.emplace_back(low, std::numeric_limits::max()); + } + return result; + } + + [[nodiscard]] auto lowest() const -> std::uint32_t + { + if (ranges_.empty()) { + return std::numeric_limits::max(); + } + return ranges_.front().first; + } + + [[nodiscard]] auto count() const -> std::uint32_t + { + return std::accumulate(ranges_.begin(), ranges_.end(), std::uint32_t{0}, + [](auto a, auto const& r) { return a + (r.second - r.first + 1); }); + } + +private: + std::vector> ranges_; +}; + +auto main() -> int +{ + static std::regex match_re{"(\\d+)-(\\d+)"}; + std::string line; + std::smatch m; + Ranges ranges; + while (std::getline(std::cin, line)) { + if (!std::regex_search(line, m, match_re)) { + std::cerr << "Unable to match: " << line << '\n'; + return 1; + } + ranges.add(std::stoul(m.str(1)), std::stoul(m.str(2))); + } + + auto inverse{ranges.inverse()}; + std::cout << "First available IP address: " << inverse.lowest() << '\n'; + std::cout << "Number of available IP addresses: " << inverse.count() << '\n'; + return 0; +} \ No newline at end of file