Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <iostream>
- #include <sstream>
- #include <regex>
- #include <unordered_map>
- #include <unordered_set>
- #include <set>
- #include <map>
- using namespace std;
- /**
- * Tuple representing the circuit element where
- * 0 - kind of the element (T, D, R, C or E)
- * 1 - number of the element (1-999999999)
- * 2 - type of the element
- * 3 - numbers of connected nodes of the element
- */
- using element_data = tuple<char, int, string, vector<int>>;
- /**
- * A map from the kind of the element to the set of numbers of existing elements
- */
- using existing_numbers_map = unordered_map<char, unordered_set<int>>;
- /**
- * A map from type of the element to connected node numbers of that element
- */
- using elements_map = unordered_map<string, set<int>>;
- /**
- * @param line - A valid string containing the state of the element
- * @return tuple represented in the string
- */
- static element_data parse_line(const string &line) {
- vector<string> tokens;
- istringstream is(line);
- string word;
- // Split the string into words ignoring any whitespace in between
- while (is >> word)
- tokens.push_back(word);
- int number = stoi(tokens[0].substr(1, string::npos));
- vector<int> nums(tokens.size() - 2);
- // Populate the vector of connection nodes
- for (int i = 2; i < tokens.size(); ++i)
- nums[i - 2] = stoi(tokens[i]);
- return make_tuple(tokens[0][0], number, tokens[1], nums);
- }
- /**
- * @param data - the element
- * @param numbers - kind of element to set of numbers map
- * @return true iff the element is a valid component in the circuit
- */
- static bool validate_element_data(const element_data &data,
- existing_numbers_map &numbers) {
- char kind;
- int number;
- const vector<int> &nodes = get<3>(data);
- tie(kind, number, ignore, ignore) = data;
- // Fail the validation if there are other element with the same kind connected to the same node
- if (numbers[kind].count(number) != 0)
- return false;
- // Get rid of duplicate integers
- set<int> unique_nodes(nodes.begin(), nodes.end());
- if (unique_nodes.size() == 1)
- return false;
- // Transistors have to be connected to 3 nodes, whereas all other kinds of elements 2
- return (kind == 'T' && nodes.size() == 3) || (kind != 'T' && nodes.size() == 2);
- }
- /**
- * Add a new element to the circuit
- * @param data - the element
- * @param numbers - kind of element to set of numbers map
- * @param nodes_connections - map representing connections of nodes
- * @param elements_by_kind - representation of the circuit grouped by kind
- */
- static void add_new_element(const element_data &data, existing_numbers_map &numbers, map<int, int> &nodes_connections,
- unordered_map<char, elements_map> &elements_by_kind) {
- char kind = get<0>(data);
- int number = get<1>(data);
- const string &type = get<2>(data);
- const vector<int> &nodes = get<3>(data);
- numbers[kind].insert(number);
- set<int> unique_nodes(nodes.begin(), nodes.end());
- // Update the number of nodes connected
- for (int node : unique_nodes) {
- if (nodes_connections.count(node) == 0)
- nodes_connections[node] = 1;
- else
- ++nodes_connections[node];
- }
- elements_map &elements = elements_by_kind[kind];
- // Init as empty set if not found
- if (elements.count(type) == 0)
- elements[type] = set<int>();
- elements[type].insert(number);
- }
- static void print_results(unordered_map<char, elements_map> &elements_by_kind) {
- // Iterate over all kinds
- for (char c : {'T', 'D', 'R', 'C', 'E'}) {
- elements_map &elements = elements_by_kind[c];
- vector<pair<string, set<int>>> vec;
- copy(elements.begin(), elements.end(), back_inserter(vec));
- // Sort the vector by element type string
- sort(vec.begin(), vec.end(), [](const pair<string, set<int>> &p1, const pair<string, set<int>> &p2) {
- return *(p1.second.begin()) < *(p2.second.begin());
- });
- // Print the results
- for (auto &p : vec) {
- auto it = p.second.begin();
- cout << c << *it;
- ++it;
- while (it != p.second.end()) {
- cout << ", " << c << *it;
- ++it;
- }
- cout << ": " << p.first << endl;
- }
- }
- }
- /**
- *
- * @param nodes_connections
- */
- static void print_nodes_warning(const map<int, int> &nodes_connections) {
- bool first = true;
- for (const auto &kv : nodes_connections) {
- if (kv.second < 2) {
- if (first) {
- cerr << "Warning, unconnected node(s): " << kv.first;
- first = false;
- } else {
- cerr << ", " << kv.first;
- }
- }
- }
- cerr << endl;
- }
- /**
- * Driver function to read the input, collect the circuit elements and print the results
- */
- static void run() {
- const char *regex_str =
- "\\s*[T|R|D|C|E]{1}[1-9]{1}[0-9]{0,8}" // Match the kind of the element followed by the number
- "\\s*[A-Z|0-9]{1}[a-z|A-Z|0-9|\\,|\\-|\\/]{0,}" // Math the type of the element
- "(\\s*(([1-9]{1}[0-9]{0,8})|0)){2,3}\\s*)"; // Match from 2 to 3 connected node numbers
- const regex re(regex_str);
- // A mapping from node N to the number of elements that connect to the node N
- map<int, int> nodes_connections({{0, 0}});
- // A mapping from the kind of the element K to the set of numbers of elements that are of kind K
- existing_numbers_map element_numbers({
- {'T', unordered_set<int>()},
- {'R', unordered_set<int>()},
- {'D', unordered_set<int>()},
- {'C', unordered_set<int>()},
- {'E', unordered_set<int>()}
- });
- // A map representing element_map instances grouped by their kind
- unordered_map<char, elements_map> elements_by_kind({
- {'T', elements_map()},
- {'R', elements_map()},
- {'D', elements_map()},
- {'C', elements_map()},
- {'E', elements_map()}
- });
- int line_number = 0;
- string line;
- while (getline(cin, line)) {
- ++line_number;
- if (!line.empty()) {
- bool is_valid = regex_match(line, re);
- if (is_valid) {
- const element_data data = parse_line(line);
- is_valid = validate_element_data(data, element_numbers);
- if (is_valid)
- add_new_element(data, element_numbers, nodes_connections, elements_by_kind);
- }
- if (!is_valid)
- cerr << "Error in line " << line_number << ": " << line << endl;
- }
- }
- print_results(elements_by_kind);
- print_nodes_warning(nodes_connections);
- }
- int main() {
- run();
- return 0;
- }
Add Comment
Please, Sign In to add comment