I'm studying the Accelerated C++ book

in the 7th chapter it teaches how to create random sentences from an input that goes like this
words between brackets work as categories
and <sentence> is the category that defines how the sentence will be organized
example:
I enter the lines:
<sentence> the <nounphrase> <verb> <location>
<nounphrase> <noun>
<nounphrase> <adj> <noun>
<adj> blue
<adj> red
<noun> table
<noun> chair
<verb> is
<verb> was
<verb> should be
<location> in the room
<location> outside

the output generated could be anything like:
the red table was outside
or
the chair should be in the room

but ... even doing everything the book asks me to I always get the same output sentence for the same input. I don't know why

could someone check it for me ? tell me if it happens to you to ? and why it's happening to me?

I would be very very grateful.

since it's kinda big I will post the code as a response.(just to make it more readable)

Recommended Answers

All 5 Replies

the codes:

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

typedef std::vector<std::string> Rule;
typedef std::vector<Rule> Rule_collection;
typedef std::map<std::string, Rule_collection> Grammar;


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

bool bracketed(const string& s)
{
	return s.size() > 1 && s[0] == '<' && s[s.size()-1] == '>';
}

vector<string> gen_sentence(const Grammar& g)
{
	vector<string> ret;
	gen_aux(g, "<sentence>", ret);
	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;
}

bool space(char c)
{
	return isspace(c);
}
bool not_space(char c)
{
	return !space(c);
}

vector<string> split(const string& s)
{
	typedef string::const_iterator iter;
	vector<string> rec;

	iter i = s.begin();

	while(i != s.end()){

		i = find_if(i, s.end(), not_space);
		
		iter j = find_if(i, s.end(), space);

		if(i != j)
			rec.push_back(string(i, j));

		i = j;
	}

	return rec;
}


int main()
{
	// generate the sentence
	vector<string> sentence = gen_sentence(read_grammar(cin));

	// write the first word, if any
	vector<string>::const_iterator it = sentence.begin();
	if(!sentence.empty()){
		cout << *it;
		++it;
	}

	while(it != sentence.end()){
		cout << " " << *it;
		++it;
	}
	cout << endl;
	return 0;
}

http://rapidshare.com/files/427250408/Generating_sentences.zip < - in case anyone find it easier to download the source files =D

You need to "seed" the RNG. If you don't, it will generate the same series of "random" numbers every time.

Look up the function srand().

At a guess, without seeing your code, it is probably because the random number generator is generating the same numbers for every time you start your program. This is normal.

Try putting this at the top of your code (possibly in main, before you need to generate random numbers).

srand (512);

This will give the random number generator a 'seed' of 512, instead of the seed that it is using by default (1, I think). You can think of the seed as the starting point for rand(). Try different values in place of 512, and you will get a different sequence.

Edit:
When you get the grip of it, you may want to base the seed on some dynamic element (like the time) instead of hardcoding a figure into it.

At a guess, without seeing your code, it is probably because the random number generator is generating the same numbers for every time you start your program. This is normal.

Try putting this at the top of your code (possibly in main, before you need to generate random numbers).

srand (512);

This will give the random number generator a 'seed' of 512, instead of the seed that it is using by default (1, I think). You can think of the seed as the starting point for rand(). Try different values in place of 512, and you will get a different sequence.

Edit:
When you get the grip of it, you may want to base the seed on some dynamic element (like the time) instead of hardcoding a figure into it.

Hard-Coding the seed is rarely a good idea. If you hard code the seed, it will generate a different sequence than it was before, but it will still always be the same sequence.

Better to learn the time method straight away.

srand((unsigned)time(0));

Hard-Coding the seed is rarely a good idea. If you hard code the seed, it will generate a different sequence than it was before, but it will still always be the same sequence.

Better to learn the time method straight away.

srand((unsigned)time(0));

Thx it works now

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.