forked from orazaro/accelerated
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path07-05-grammar.cpp
134 lines (119 loc) · 3.12 KB
/
07-05-grammar.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <map>
#include <cctype>
#include <cstdlib>
#include <ctime>
#include <stdexcept>
// isspace is overloaded so we use wrapper function as argument for find_if
inline bool space(char c)
{
return isspace(c);
}
inline bool not_space(char c)
{
return !isspace(c);
}
std::vector<std::string> split(const std::string& str)
{
typedef std::string::const_iterator iter;
std::vector<std::string> ret;
iter i = str.begin();
while(i != str.end())
{
// ignore leading spaces
i = find_if(i, str.end(), not_space);
// find end of next word
iter j = find_if(i, str.end(), space);
if(i != str.end())
ret.push_back(std::string(i, j));
i = j;
}
return ret;
}
typedef std::vector<std::string> Rule;
typedef std::vector<Rule> Rule_collection;
typedef std::map<std::string, Rule_collection> Grammar;
Grammar read_grammar(std::istream& in)
{
using namespace std;
Grammar ret;
string line;
while(getline(in, line)) {
vector<string> entry = split(line);
if(!entry.empty())
ret[entry[0]].push_back(
Rule(entry.begin() + 1, entry.end())
);
}
return ret;
}
bool bracketed(const std::string& s)
{
return s.size() > 1 && s[0] == '<' && s[s.size()-1] == '>';
}
// return a random integer in the range [0, n)
int nrand(int n)
{
if(n <= 0 || n > RAND_MAX)
throw std::domain_error("Argument to nrand is out of range");
const int bucket_size = RAND_MAX / n;
int r;
do r = random() / bucket_size;
while(r >= n);
return r;
}
void gen_aux(const Grammar& g, const std::string& word,
std::list<std::string>& ret)
{
if(!bracketed(word)) {
ret.push_back(word);
} else {
// locate the rule that corresponds to word
Grammar::const_iterator it = g.find(word);
if(it == g.end())
throw std::logic_error("empty rule");
// fetch the set of possible rules
const Rule_collection& c = it->second;
// from which we select one at random
const Rule& r = c[nrand(c.size())];
// recursivelly expand the selected rule
for(Rule::const_iterator i = r.begin(); i != r.end(); ++i)
gen_aux(g, *i, ret);
}
}
std::list<std::string> gen_sentence(const Grammar& g)
{
using namespace std;
list<string> ret;
gen_aux(g, "<sentence>", ret);
return ret;
}
std::string concatenate(const std::list<std::string>& v)
{
using namespace std;
string ret;
list<string>::const_iterator it = v.begin();
if(!v.empty()) {
copy(it->begin(), it->end(), back_inserter(ret));
++it;
}
for(;it != v.end(); ++it) {
ret.push_back(' ');
copy(it->begin(), it->end(), back_inserter(ret));
}
return ret;
}
int main()
{
srandom(time(NULL));
Grammar g = read_grammar(std::cin);
for(int i = 0; i < 20; ++i) {
std::list<std::string> ret = gen_sentence(g);
std::string s = concatenate(ret);
std::cout << s << std::endl;
}
return 0;
}