252 lines
6.0 KiB
C++
252 lines
6.0 KiB
C++
|
#ifdef _MSC_VER
|
|||
|
#pragma warning(disable:4503) // `silence compiler complaints about generated names being too long'
|
|||
|
#endif
|
|||
|
|
|||
|
#include <algorithm>
|
|||
|
#include <cstdlib>
|
|||
|
#include <iostream>
|
|||
|
#include <map>
|
|||
|
#include <stdexcept>
|
|||
|
#include <string>
|
|||
|
#include <vector>
|
|||
|
|
|||
|
#include "split.h"
|
|||
|
#include <time.h>
|
|||
|
|
|||
|
using std::istream; using std::cin;
|
|||
|
using std::copy; using std::cout;
|
|||
|
using std::endl; using std::find;
|
|||
|
using std::getline; using std::logic_error;
|
|||
|
using std::map; using std::string;
|
|||
|
using std::vector; using std::domain_error;
|
|||
|
using std::rand;
|
|||
|
|
|||
|
typedef vector<string> Rule;
|
|||
|
typedef vector<Rule> Rule_collection;
|
|||
|
typedef map<string, Rule_collection> Grammar;
|
|||
|
|
|||
|
// read a grammar from a given input stream
|
|||
|
Grammar read_grammar(istream& in)
|
|||
|
{
|
|||
|
Grammar ret;
|
|||
|
string line;
|
|||
|
|
|||
|
// read the input
|
|||
|
while (getline(in, line)) {
|
|||
|
|
|||
|
// `split' the input into words
|
|||
|
vector<string> entry = split(line);
|
|||
|
|
|||
|
if (!entry.empty())
|
|||
|
// use the category to store the associated rule
|
|||
|
ret[entry[0]].push_back(
|
|||
|
Rule(entry.begin() + 1, entry.end()));
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
void gen_aux(const Grammar&, const string&, vector<string>&);
|
|||
|
|
|||
|
int nrand(int);
|
|||
|
|
|||
|
vector<string> gen_sentence(const Grammar& g)
|
|||
|
{
|
|||
|
vector<string> ret;
|
|||
|
gen_aux(g, "<sentence>", ret);
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
bool bracketed(const string& s)
|
|||
|
{
|
|||
|
return s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>';
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
gen_aux(const Grammar& g, const string& word, vector<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 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())];
|
|||
|
|
|||
|
// recursively expand the selected rule
|
|||
|
for (Rule::const_iterator i = r.begin(); i != r.end(); ++i)
|
|||
|
gen_aux(g, *i, ret);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int main()
|
|||
|
{
|
|||
|
// generate the sentence
|
|||
|
vector<string> sentence = gen_sentence(read_grammar(cin));
|
|||
|
|
|||
|
// write the first word, if any
|
|||
|
#ifdef _MSC_VER
|
|||
|
std::vector<string>::const_iterator it = sentence.begin();
|
|||
|
#else
|
|||
|
vector<string>::const_iterator it = sentence.begin();
|
|||
|
#endif
|
|||
|
if (!sentence.empty()) {
|
|||
|
cout << *it;
|
|||
|
++it;
|
|||
|
}
|
|||
|
|
|||
|
// write the rest of the words, each preceded by a space
|
|||
|
while (it != sentence.end()) {
|
|||
|
cout << " " << *it;
|
|||
|
++it;
|
|||
|
}
|
|||
|
|
|||
|
cout << endl;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
// return a random integer in the range `[0,' `n)'
|
|||
|
int nrand(int n)
|
|||
|
{
|
|||
|
if (n <= 0 || n > RAND_MAX)
|
|||
|
throw domain_error("Argument to nrand is out of range");
|
|||
|
|
|||
|
const int bucket_size = RAND_MAX / n;
|
|||
|
int r;
|
|||
|
|
|||
|
do r = rand() / bucket_size;
|
|||
|
while (r >= n);
|
|||
|
|
|||
|
return r;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#ifdef _MSC_VER
|
|||
|
#pragma warning(disable:4503) // <20>رձ<D8B1><D5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>棬<EFBFBD><E6A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><C9B5><EFBFBD><EFBFBD>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD>ı<EFBFBD>Թ
|
|||
|
#endif
|
|||
|
|
|||
|
#include <algorithm> // <20><><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>⣬<EFBFBD>ṩ<EFBFBD><E1B9A9><EFBFBD>õ<EFBFBD><C3B5>㷨
|
|||
|
#include <cstdlib> // <20><><EFBFBD><EFBFBD>C<EFBFBD><43><EFBFBD>⣬<EFBFBD><E2A3AC><EFBFBD><EFBFBD>rand()<29><><EFBFBD><EFBFBD>
|
|||
|
#include <iostream> // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
#include <map> // <20><><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>map<61><70><EFBFBD><EFBFBD>
|
|||
|
#include <stdexcept> // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD>⣬<EFBFBD>ṩ<EFBFBD><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣
|
|||
|
#include <string> // <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
#include <vector> // <20><><EFBFBD>붯̬<EBB6AF><CCAC><EFBFBD>飨vector<6F><72><EFBFBD><EFBFBD>
|
|||
|
#include "split.h" // <20><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>split.hͷ<68>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ٶ<EFBFBD><D9B6>ṩ<EFBFBD><E1B9A9><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9>ܣ<EFBFBD>
|
|||
|
#include <time.h> // <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>⣬֧<E2A3AC><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
using std::istream; using std::cin;
|
|||
|
using std::copy; using std::cout;
|
|||
|
using std::endl; using std::find;
|
|||
|
using std::getline; using std::logic_error;
|
|||
|
using std::map; using std::string;
|
|||
|
using std::vector; using std::domain_error;
|
|||
|
using std::rand; // <20><><EFBFBD><EFBFBD>rand<6E><64><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFB7A8><EFBFBD><EFBFBD><EFBFBD>ϣ<F2BCAFBA><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
typedef vector<string> Rule; // һ<><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
|||
|
typedef vector<Rule> Rule_collection; // <20><><EFBFBD><EFBFBD><F2BCAFBA>ǹ<EFBFBD><C7B9><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
|||
|
typedef map<string, Rule_collection> Grammar; // <20><EFBFBD><EFB7A8>һ<EFBFBD><D2BB>ӳ<EFBFBD>䣺<EFBFBD><E4A3BA><EFBFBD><EFBFBD> -> <20><><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡ<EFBFBD><EFBFBD><EFB7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
Grammar read_grammar(istream& in) {
|
|||
|
Grammar ret; // <20><><EFBFBD>ڴ洢<DAB4>
|
|||
|
string line;
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡÿһ<C3BF><D2BB>
|
|||
|
while (getline(in, line)) {
|
|||
|
// <20><><EFBFBD><EFBFBD>ǰ<EFBFBD>в<EFBFBD><D0B2>ֳɵ<D6B3><C9B5><EFBFBD>
|
|||
|
vector<string> entry = split(line);
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><D6B3>ĵ<EFBFBD><C4B5>ʲ<EFBFBD>Ϊ<EFBFBD>գ<EFBFBD><D5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD>
|
|||
|
if (!entry.empty())
|
|||
|
ret[entry[0]].push_back(
|
|||
|
Rule(entry.begin() + 1, entry.end())); // ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊkey<65><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊvalue
|
|||
|
}
|
|||
|
return ret; // <20><><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
|
|||
|
// <20>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE>ӵĸ<D3B5><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
void gen_aux(const Grammar&, const string&, vector<string>&);
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7>[0, n)<29>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
int nrand(int);
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD><EFBFBD>gen_aux<75><78><EFBFBD>еݹ<D0B5><DDB9><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
vector<string> gen_sentence(const Grammar& g) {
|
|||
|
vector<string> ret;
|
|||
|
gen_aux(g, "<sentence>", ret); // <20><><sentence><3E><>ʼ<EFBFBD><CABC><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD>
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
// <20>ж<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>DZ<EFBFBD><C7B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ű<EFBFBD>Χ<EFBFBD><CEA7>
|
|||
|
bool bracketed(const string& s) {
|
|||
|
return s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>';
|
|||
|
}
|
|||
|
|
|||
|
// <20>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>е<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>
|
|||
|
void gen_aux(const Grammar& g, const string& word, vector<string>& ret) {
|
|||
|
if (!bracketed(word)) {
|
|||
|
ret.push_back(word); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><C7B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ű<EFBFBD>Χ<EFBFBD>ĵ<EFBFBD><C4B5>ʣ<EFBFBD>ֱ<EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
else {
|
|||
|
// <20><><EFBFBD>Ҷ<EFBFBD>Ӧ<EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD>
|
|||
|
Grammar::const_iterator it = g.find(word);
|
|||
|
if (it == g.end()) // <20><><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD><D7B3>쳣
|
|||
|
throw logic_error("empty rule");
|
|||
|
|
|||
|
// <20><>ȡ<EFBFBD>õ<EFBFBD><C3B5>ʵĹ<CAB5><C4B9><EFBFBD>
|
|||
|
const Rule_collection& c = it->second;
|
|||
|
|
|||
|
// <20>ӹ<EFBFBD><D3B9><EFBFBD><F2BCAFBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
const Rule& r = c[nrand(c.size())];
|
|||
|
|
|||
|
// <20><>ѡ<EFBFBD>еĹ<D0B5><C4B9><EFBFBD><EFBFBD>е<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>еݹ鴦<DDB9><E9B4A6>
|
|||
|
for (Rule::const_iterator i = r.begin(); i != r.end(); ++i)
|
|||
|
gen_aux(g, *i, ret);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int main() {
|
|||
|
// <20><><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD>
|
|||
|
vector<string> sentence = gen_sentence(read_grammar(cin));
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>
|
|||
|
vector<string>::const_iterator it = sentence.begin();
|
|||
|
if (!sentence.empty()) {
|
|||
|
cout << *it;
|
|||
|
++it;
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD>ĵ<EFBFBD><C4B5>ʣ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>һ<EFBFBD><D2BB><EFBFBD>ո<EFBFBD>
|
|||
|
while (it != sentence.end()) {
|
|||
|
cout << " " << *it;
|
|||
|
++it;
|
|||
|
}
|
|||
|
|
|||
|
cout << endl; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7>[0, n)
|
|||
|
int nrand(int n) {
|
|||
|
if (n <= 0 || n > RAND_MAX)
|
|||
|
throw domain_error("Argument to nrand is out of range");
|
|||
|
|
|||
|
const int bucket_size = RAND_MAX / n; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷֲ<C8B7>
|
|||
|
int r;
|
|||
|
|
|||
|
// ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>Χ<EFBFBD><CEA7>
|
|||
|
do r = rand() / bucket_size;
|
|||
|
while (r >= n);
|
|||
|
|
|||
|
return r;
|
|||
|
}
|