#pragma once #include #include #include #include #include #include namespace aoc2019 { template inline std::from_chars_result from_chars(std::string_view str, T &value) { return std::from_chars(str.data(), str.data() + str.size(), value); } template void combine_hash(std::size_t &seed, const T &o) { // Algorithm taken from boost::combine_hash. std::hash hash{}; seed ^= hash(o) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } template std::istream &read_line_numbers_and_garbage(std::istream &input, OutputIt output) { ValueType v; char c; while (input && (c = input.peek()) != '\n') { if (c == '-' || std::isdigit(c)) { input >> v; *output = v; ++output; } else { input.ignore(); } } input.get(); return input; } std::string_view strtok(std::string_view &str, char token = ','); std::deque 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; explicit IntCodeComputer(std::vector program, std::deque initial_inputs = {}); explicit IntCodeComputer(std::istream &program_stream, std::deque initial_inputs = {}); void run(); void connectOutput(IntCodeComputer &computer); void connectOutput(std::deque &sink); void sendInput(value_t input); void sendInputs(std::string_view str); [[nodiscard]] bool isTerminated() const; [[nodiscard]] const std::deque ¤tInputs() const; value_t &operator[](std::size_t index); const value_t &operator[](std::size_t index) const; static std::vector read_intcode(std::istream &input); private: std::vector program; std::deque inputs = {}; std::deque *outputSink = nullptr; int ip = 0; int relative = 0; bool halted = false; [[nodiscard]] value_t &interpret_value(int pos); }; }