# map을 이용한 문장 생성 프로그램map을 사용하여 문장 구조, 즉 문법을 정의하고, 그 정의된 문법을 만족하는 문장을 무작위로 생성하는 프로그램
makesentence.cpp#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
usingnamespacestd;
typedef vector<string> Rule;
typedef vector<Rule> Rule_collection;
typedef map<string, Rule_collection> Grammar;
/* 인자가 공백문자이면 true, 그렇지 않다면 false를 리턴 */
bool space(char c)
{
return isspace(c);
}
/* 인자가 공백문자이면 false, 그렇지 않다면 ture를 리턴 */
bool not_space(char c)
{
return !isspace(c);
}
vector<string> split(conststring& str)
{
typedefstring::const_iterator iter;
vector<string> ret;
iter i=str.begin();
while(i!=str.end())
{
// 맨 앞의 빈칸을 무시
i=find_if(i, str.end(), not_space);
// 단어의 끝을 검색
iter j=find_if(i, str.end(), space);
// [i,j) 범위의 단어를 복사
if(i!=str.end())
ret.push_back(string(i,j));
// 다음 단어를 검색
i=j;
}
return ret;
}
Grammar read_grammar(istream& in)
{
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;
}
int nrand(int n)
{
if(n<=0 || n>RAND_MAX)
throw domain_error("Argument to nrand is out of range");
constint bucket_size = RAND_MAX / n; // 32767 / 10 3276
int r;
do r=rand() / bucket_size;
while(r >= n); //
return r;
}
bool bracketed(conststring& s)
{
return s.size() > 1 && s[0] == '<' && s[s.size() -1] == '>';
}
void gen_aux(const Grammar& g, conststring& word, vector<string>& ret)
{
// 입력 string이 각괄호로 둘러쌓여있지 않다면 그 자체로 출력의 일부가 된다.
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);
}
}
vector<string> gen_sentence(const Grammar& g)
{
vector<string> ret;
gen_aux(g, "<sentence>", ret);
return ret;
}
int main()
{
vector<string> sentence = gen_sentence(read_grammar(cin));
vector<string>::const_iterator it=sentence.begin();
if(!sentence.empty())
{
cout<<*it;
++it;
}
while(it!=sentence.end())
{
cout<<" "<<*it;
++it;
}
cout<<endl;
return0;
}