252 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}