-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
119 lines (103 loc) · 3.36 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <fstream>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include "boost/fusion/adapted.hpp"
#include "boost/spirit/home/x3.hpp"
std::vector<char> readFile()
{
std::ifstream in { "input.txt", std::ios::ate };
std::vector<char> buffer(in.tellg());
in.seekg(std::ios::beg);
in.read(buffer.data(), buffer.size());
return buffer;
}
using color_type = std::string;
using child_type = std::pair<int, color_type>;
using rule_type = boost::tuple<color_type, std::vector<child_type>>;
using rules_type = std::unordered_map<color_type, std::vector<child_type>>;
std::ostream &operator<<(std::ostream &out, const child_type &child)
{
out << child.first << "@" << child.second;
return out;
}
std::ostream &operator<<(std::ostream &out, const rule_type &rule)
{
out << rule.get<0>() << ": ";
for (const auto &item : rule.get<1>()) out << item << " ";
return out;
}
template <typename Iterator> auto parseBuffer(Iterator begin, Iterator end)
{
using namespace boost::spirit;
using x3::alpha;
using x3::eol;
using x3::int_;
using x3::lexeme;
using x3::lit;
using x3::omit;
using x3::rule;
using x3::ascii::space;
auto word_ = lexeme[+alpha];
struct color_tag;
auto color_ = rule<color_tag, color_type>() = word_ >> word_;
auto bag_ = color_ >> (lit("bags") | lit("bag"));
struct child_tag;
auto child_ = rule<child_tag, child_type>() = (int_ >> bag_);
struct rule_tag;
auto no_bags_ = lit("no other bags");
auto rule_ = rule<rule_tag, rule_type>() = bag_ >> lit("contain") >> ((child_ % ",") | no_bags_) >> ".";
auto rules_ = +rule_;
rules_type value;
auto result = x3::phrase_parse(begin, end, rules_, space, value);
std::cout << "Parser " << (result ? "success" : "failure") << " at " << std::string(begin, begin) << std::endl;
std::cout << "Read " << value.size() << " rules" << std::endl;
return value;
}
void f1(const rules_type &rules, const std::string &color)
{
std::unordered_set<color_type> parents;
std::queue<color_type> queue;
queue.push(color);
while (!queue.empty()) {
auto current = queue.front();
for (const auto &[parent, children] : rules) {
for (const auto &[count, child] : children) {
if (child == current) {
parents.insert(parent);
queue.push(parent);
}
}
}
queue.pop();
}
std::cout << "Parents: " << parents.size() << std::endl;
}
int f2_impl(const rules_type &rules, const color_type &color, std::unordered_map<color_type, int> &memoizer)
{
int total = 0;
for (const auto &[count, child] : rules.at(color)) {
int to_add;
if (auto it = memoizer.find(child); it != memoizer.end()) {
to_add = it->second;
} else {
to_add = f2_impl(rules, child, memoizer);
memoizer[child] = to_add;
}
total += count * (1 + to_add);
}
return total;
}
void f2(const rules_type &rules, const color_type &color)
{
std::unordered_map<color_type, int> cache;
std::cout << "Children: " << f2_impl(rules, color, cache) << std::endl;
}
int main()
{
const auto buffer = readFile();
auto rules = parseBuffer(buffer.begin(), buffer.end());
f1(rules, "shinygold");
f2(rules, "shinygold");
}