Add 2016 day 20 puzzles

This commit is contained in:
2021-12-07 16:09:20 +00:00
parent 30c5f724bc
commit d3622ff806
2 changed files with 188 additions and 0 deletions

87
2016/puzzle-20-01.cc Normal file
View File

@@ -0,0 +1,87 @@
#include <iostream>
#include <regex>
#include <string>
struct Ranges
{
void add(std::uint32_t low, std::uint32_t high)
{
static constexpr auto max{std::numeric_limits<std::uint32_t>::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<std::uint32_t>::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<std::uint32_t>::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<std::uint32_t>::max()});
}
return result;
}
auto lowest() const -> std::uint32_t
{
if (ranges_.empty()) {
return std::numeric_limits<std::uint32_t>::max();
}
return ranges_.front().first;
}
private:
std::vector<std::pair<std::uint32_t, std::uint32_t>> 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;
}

101
2016/puzzle-20-02.cc Normal file
View File

@@ -0,0 +1,101 @@
#include <iomanip>
#include <iostream>
#include <numeric>
#include <regex>
#include <string>
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<std::uint32_t>::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<std::uint32_t>::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<std::uint32_t>::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<std::uint32_t>::max());
}
return result;
}
[[nodiscard]] auto lowest() const -> std::uint32_t
{
if (ranges_.empty()) {
return std::numeric_limits<std::uint32_t>::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<std::pair<std::uint32_t, std::uint32_t>> 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;
}