#ifdef _MSC_VER #pragma warning(disable:4503) // `silence compiler complaints about generated names being too long' #endif #include #include #include #include #include #include #include #include "split.h" #include 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 Rule; typedef vector Rule_collection; typedef map 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 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&); int nrand(int); vector gen_sentence(const Grammar& g) { vector ret; gen_aux(g, "", 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& 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 sentence = gen_sentence(read_grammar(cin)); // write the first word, if any #ifdef _MSC_VER std::vector::const_iterator it = sentence.begin(); #else vector::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) // 关闭编译器警告,避免对生成的名称过长的抱怨 #endif #include // 引入算法库,提供常用的算法 #include // 引入C标准库,包含rand()函数 #include // 引入标准输入输出流库 #include // 引入映射容器(map)库 #include // 引入标准异常库,提供逻辑错误和域错误等异常 #include // 引入字符串库 #include // 引入动态数组(vector)库 #include "split.h" // 引入自定义的split.h头文件(假定提供了字符串拆分功能) #include // 引入时间库,支持随机数生成 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; // 引入rand函数 // 定义规则(字符串集合)和语法(规则集合)的类型 typedef vector Rule; // 一个规则是字符串的集合 typedef vector Rule_collection; // 规则集合是规则的集合 typedef map Grammar; // 语法是一个映射:类别 -> 规则集合 // 从输入流中读取语法并返回 Grammar read_grammar(istream& in) { Grammar ret; // 用于存储语法 string line; // 持续读取每一行 while (getline(in, line)) { // 将当前行拆分成单词 vector entry = split(line); // 如果拆分出的单词不为空,则根据类别存储规则 if (!entry.empty()) ret[entry[0]].push_back( Rule(entry.begin() + 1, entry.end())); // 使用类别作为key,规则作为value } return ret; // 返回语法 } // 递归生成句子的辅助函数 void gen_aux(const Grammar&, const string&, vector&); // 返回一个范围在[0, n)内的随机整数 int nrand(int); // 生成一个句子,调用gen_aux进行递归生成 vector gen_sentence(const Grammar& g) { vector ret; gen_aux(g, "", 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& ret) { if (!bracketed(word)) { ret.push_back(word); // 如果不是被尖括号包围的单词,直接加入句子 } else { // 查找对应的规则 Grammar::const_iterator it = g.find(word); if (it == g.end()) // 如果没有找到规则,抛出异常 throw logic_error("empty rule"); // 获取该单词的规则集合 const Rule_collection& c = it->second; // 从规则集合中随机选择一个规则 const Rule& r = c[nrand(c.size())]; // 对选中的规则中的每个单词进行递归处理 for (Rule::const_iterator i = r.begin(); i != r.end(); ++i) gen_aux(g, *i, ret); } } int main() { // 生成句子 vector sentence = gen_sentence(read_grammar(cin)); // 输出第一个单词(如果有) vector::const_iterator it = sentence.begin(); if (!sentence.empty()) { cout << *it; ++it; } // 输出剩余的单词,每个单词前加一个空格 while (it != sentence.end()) { cout << " " << *it; ++it; } cout << endl; // 输出换行 return 0; } // 返回一个随机整数,范围在[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; }