mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-27 13:50:32 +01:00
Make topological sort generic.
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include "days.hpp"
|
#include "days.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
typedef std::pair<std::string, std::int64_t> requirement_t;
|
typedef std::pair<std::string, std::int64_t> requirement_t;
|
||||||
@@ -68,7 +69,7 @@ namespace {
|
|||||||
std::vector<std::string> topological_order(const std::map<reqlist_t, reqlist_t> &recipes) {
|
std::vector<std::string> topological_order(const std::map<reqlist_t, reqlist_t> &recipes) {
|
||||||
std::vector<std::string> order;
|
std::vector<std::string> order;
|
||||||
|
|
||||||
std::unordered_map<std::string_view, std::vector<std::string>> edges;
|
std::unordered_map<std::string, std::vector<std::string>> edges;
|
||||||
for (auto &entry : recipes) {
|
for (auto &entry : recipes) {
|
||||||
for (auto &production : entry.first) {
|
for (auto &production : entry.first) {
|
||||||
std::transform(entry.second.begin(), entry.second.end(), std::back_inserter(edges[production.first]),
|
std::transform(entry.second.begin(), entry.second.end(), std::back_inserter(edges[production.first]),
|
||||||
@@ -78,28 +79,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string_view, int> incoming_edge_count;
|
return aoc2019::topological_sort(edges);
|
||||||
for (const auto &entry : edges) {
|
|
||||||
for (const auto &parent : entry.second) {
|
|
||||||
incoming_edge_count[parent]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::deque<std::string_view> 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::int64_t ore_to_fuel(const std::map<reqlist_t, reqlist_t> &recipes, std::int64_t amount = 1) {
|
std::int64_t ore_to_fuel(const std::map<reqlist_t, reqlist_t> &recipes, std::int64_t amount = 1) {
|
||||||
|
|||||||
@@ -27,6 +27,49 @@ namespace aoc2019 {
|
|||||||
|
|
||||||
std::vector<int> run_intcode(std::vector<int> &program, std::deque<int> inputs = {});
|
std::vector<int> run_intcode(std::vector<int> &program, std::deque<int> inputs = {});
|
||||||
|
|
||||||
|
template<class Node>
|
||||||
|
std::vector<Node> topological_sort(const std::unordered_map<Node, std::vector<Node>> &edge_list) {
|
||||||
|
std::unordered_map<Node, int> 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<Node> order;
|
||||||
|
std::deque<Node> 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 {
|
class IntCodeComputer {
|
||||||
public:
|
public:
|
||||||
typedef std::int64_t value_t;
|
typedef std::int64_t value_t;
|
||||||
|
|||||||
Reference in New Issue
Block a user