From a655436ac6ec4470d1322721400b3cafe2157ab0 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sat, 14 Dec 2019 15:52:55 +0100 Subject: [PATCH] Make topological sort generic. --- 2019/src/day14.cpp | 26 +++----------------------- 2019/src/utils.hpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/2019/src/day14.cpp b/2019/src/day14.cpp index 0f5339a..2abebfd 100644 --- a/2019/src/day14.cpp +++ b/2019/src/day14.cpp @@ -7,6 +7,7 @@ #include #include #include "days.hpp" +#include "utils.hpp" namespace { typedef std::pair requirement_t; @@ -68,7 +69,7 @@ namespace { std::vector topological_order(const std::map &recipes) { std::vector order; - std::unordered_map> edges; + std::unordered_map> edges; for (auto &entry : recipes) { for (auto &production : entry.first) { std::transform(entry.second.begin(), entry.second.end(), std::back_inserter(edges[production.first]), @@ -78,28 +79,7 @@ namespace { } } - std::unordered_map incoming_edge_count; - for (const auto &entry : edges) { - for (const auto &parent : entry.second) { - incoming_edge_count[parent]++; - } - } - - std::deque childless{"FUEL"}; - - while (!childless.empty()) { - auto current = childless.front(); - childless.pop_front(); - order.emplace_back(current); - - for (const auto &parent : edges[current]) { - if (--incoming_edge_count[parent] == 0) { - childless.push_back(parent); - } - } - } - - return order; + return aoc2019::topological_sort(edges); } std::int64_t ore_to_fuel(const std::map &recipes, std::int64_t amount = 1) { diff --git a/2019/src/utils.hpp b/2019/src/utils.hpp index 7ae5f2b..a7f04d0 100644 --- a/2019/src/utils.hpp +++ b/2019/src/utils.hpp @@ -27,6 +27,49 @@ namespace aoc2019 { std::vector run_intcode(std::vector &program, std::deque inputs = {}); + template + std::vector topological_sort(const std::unordered_map> &edge_list) { + std::unordered_map incoming_edges; + + for (auto &entry : edge_list) { + // Ensure entry for parent exist + incoming_edges[entry.first] += 0; + + for (auto &node : entry.second) { + incoming_edges[node]++; + } + } + + std::vector order; + std::deque childless; + + for (auto &entry : incoming_edges) { + if (!entry.second) { + childless.push_back(entry.first); + } + } + + while (!childless.empty()) { + auto current = childless.front(); + childless.pop_front(); + order.emplace_back(current); + + if (auto it = edge_list.find(current); it != edge_list.end()) { + for (const auto &parent : it->second) { + if (--incoming_edges[parent] == 0) { + childless.push_back(parent); + } + } + } + } + + if (order.size() != incoming_edges.size()) { + throw std::domain_error("Not a DAG."); + } + + return order; + } + class IntCodeComputer { public: typedef std::int64_t value_t;