diff --git a/2024/day05/part2.cc b/2024/day05/part2.cc new file mode 100644 index 0000000..3b98d15 --- /dev/null +++ b/2024/day05/part2.cc @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include + +class print_job { + std::vector page_order; + std::set pages; +public: + print_job(std::stringstream& ss); + bool before(int before, int after) const; + bool contains(int page) const; + int middle() const; + template + void sort(Compare comp); +}; + +print_job::print_job(std::stringstream& ss) { + int page; + while (ss >> page) { + page_order.emplace_back(page); + pages.emplace(page); + ss.ignore(1, ','); + } +} + +bool print_job::before(int before, int after) const { + return std::distance(page_order.begin(), std::find(page_order.begin(), page_order.end(), before)) + < std::distance(page_order.begin(), std::find(page_order.begin(), page_order.end(), after)); +} + +bool print_job::contains(int page) const { + return pages.contains(page); +} + +int print_job::middle() const { + return page_order[page_order.size() / 2]; +} + +template +void print_job::sort(Compare comp) { + std::sort(page_order.begin(), page_order.end(), comp); +} + +class rule { +public: + int before; + int after; + rule(std::stringstream& ss); + bool valid(const print_job& job) const; +}; + +rule::rule(std::stringstream& ss) { + ss >> before; + ss.ignore(1, '|'); + ss >> after; +} + +bool rule::valid(const print_job& job) const { + return !job.contains(before) || !job.contains(after) || job.before(before, after); +} + +class rule_set { + std::vector rules; +public: + rule_set(std::istream& is); + bool valid(const print_job& job) const; + bool before(int a, int b) const; +}; + +rule_set::rule_set(std::istream& is) { + std::string line; + while (std::getline(is, line)) { + if (line == "") { + return; + } + std::stringstream ss(line); + rules.emplace_back(ss); + } +} + +bool rule_set::valid(const print_job& job) const { + return std::ranges::all_of(rules, [&](auto rule) { return rule.valid(job); }); +} + +bool rule_set::before(int a, int b) const { + for (const rule& r : rules) { + if (r.before == a && r.after == b) { + return true; + } + } + return false; +} + +int main() { + rule_set rules(std::cin); + std::string line; + int sum = 0; + while (std::getline(std::cin, line)) { + std::stringstream ss(line); + print_job job(ss); + if (!rules.valid(job)) { + job.sort([&](int a, int b) { return rules.before(a, b); }); + sum += job.middle(); + } + } + std::cout << sum << std::endl; + return EXIT_SUCCESS; +}