diff --git a/2017/puzzle-07-01.cc b/2017/puzzle-07-01.cc new file mode 100644 index 0000000..05d4b15 --- /dev/null +++ b/2017/puzzle-07-01.cc @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + +using UInt = unsigned long; + +auto main() -> int +{ + static std::regex top_re{R"(^([a-z]+) \((\d+)\)$)"}; + static std::regex node_re{R"(^([a-z]+) \((\d+)\) -> (.+)$)"}; + + std::string line; + std::map weights; + std::set children_nodes; + std::set maybe_root; + + while (std::getline(std::cin, line) && !line.empty()) { + std::smatch m; + if (std::regex_search(line, m, node_re)) { + auto weight{std::stoul(m.str(2))}; + auto node{m.str(1)}; + auto children{m.str(3)}; + weights.insert({node, weight}); + maybe_root.insert(node); + std::size_t idx{0}; + while (idx < children.size()) { + if (children[idx] == ' ' || children[idx] == ',') { + ++idx; + continue; + } + + std::string child; + while (idx < children.size() && children[idx] != ',') { + child.push_back(children[idx]); + ++idx; + } + children_nodes.insert(child); + } + } + else if (std::regex_search(line, m, top_re)) { + auto weight{std::stoul(m.str(2))}; + auto const& node{m.str(1)}; + weights.insert({node, weight}); + children_nodes.insert(node); + } + } + + std::set root; + std::set_difference(maybe_root.begin(), maybe_root.end(), children_nodes.begin(), + children_nodes.end(), std::inserter(root, root.end())); + std::string prefix = "Root = "; + for (auto const& n : root) { + std::cout << prefix << n; + prefix = ", "; + } + std::cout << '\n'; +} diff --git a/2017/puzzle-07-02.cc b/2017/puzzle-07-02.cc new file mode 100644 index 0000000..d845694 --- /dev/null +++ b/2017/puzzle-07-02.cc @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include + +using UInt = unsigned long; +using Nodes = std::multimap; +using WeightMap = std::map>; + +void find_broken(Nodes const& nodes, WeightMap& weights, std::string const& node) +{ + auto [begin_it, end_it] = nodes.equal_range(node); + UInt count{0}; + UInt total_weight{0}; + UInt weight1{0}; + UInt weight2{0}; + std::string name1; + std::string name2; + for (auto it{begin_it}; it != end_it; ++it) { + find_broken(nodes, weights, it->second); + ++count; + auto w{weights.find(it->second)->second.second}; + total_weight += w; + if (weight1 == 0) { + weight1 = w; + name1 = it->second; + } + else if (w != weight1 && weight2 == 0) { + weight2 = w; + name2 = it->second; + } + else if (w != weight1 && w != weight2) { + abort(); + } + } + + std::string wrong_name; + UInt wrong_weight{0}; + UInt correct_weight{0}; + if (weight2 != 0 && (weight1 * (count - 1) + weight2) == total_weight) { + wrong_name = name2; + wrong_weight = weight2; + correct_weight = weight1; + } + if (weight2 != 0 && (weight2 * (count - 1) + weight1) == total_weight) { + wrong_name = name1; + wrong_weight = weight1; + correct_weight = weight2; + } + + if (wrong_weight != 0) { + std::cout << "Wrong node: " << wrong_name << "\n"; + std::cout << "Total weight is " << wrong_weight << " but should be " << correct_weight << '\n'; + std::cout << "Node weight should therefore be: " + << weights.find(wrong_name)->second.first + correct_weight - wrong_weight << '\n'; + std::exit(0); + } + + auto it{weights.find(node)}; + assert(it != weights.end()); + it->second.second = it->second.first + total_weight; +} + +auto main() -> int +{ + static std::regex top_re{R"(^([a-z]+) \((\d+)\)$)"}; + static std::regex node_re{R"(^([a-z]+) \((\d+)\) -> (.+)$)"}; + + std::string line; + WeightMap weights; + Nodes nodes; + std::set children_nodes; + std::set maybe_root; + + while (std::getline(std::cin, line) && !line.empty()) { + std::smatch m; + if (std::regex_search(line, m, node_re)) { + auto weight{std::stoul(m.str(2))}; + auto node{m.str(1)}; + auto children{m.str(3)}; + weights.insert({node, {weight, 0}}); + maybe_root.insert(node); + std::size_t idx{0}; + while (idx < children.size()) { + if (children[idx] == ' ' || children[idx] == ',') { + ++idx; + continue; + } + + std::string child; + while (idx < children.size() && children[idx] != ',') { + child.push_back(children[idx]); + ++idx; + } + children_nodes.insert(child); + nodes.insert({node, child}); + } + } + else if (std::regex_search(line, m, top_re)) { + auto weight{std::stoul(m.str(2))}; + auto const& node{m.str(1)}; + weights.insert({node, {weight, weight}}); + children_nodes.insert(node); + } + } + + std::set root; + std::set_difference(maybe_root.begin(), maybe_root.end(), children_nodes.begin(), + children_nodes.end(), std::inserter(root, root.end())); + std::string prefix = "Root = "; + for (auto const& n : root) { + std::cout << prefix << n; + prefix = ", "; + } + std::cout << '\n'; + find_broken(nodes, weights, *root.begin()); +}