CSc 220 Assignment 3

What You Say?

Assigned
Due

Sep 16
80 pts
Sep 30

Write a C++ program which reads lists of proper names, adjectives, nouns and verbs. From these, it chooses parts at random and prints a sentence of the form

name verb the [ adjective1 [ adjective2 ] ] noun
where each part (except the) is chosen at random from the appropriate list. The adjectives may or may not appear, also decided at random. The first adjective appears with 75% probability. If the first appears, roll again and add second one with 75% probability. If a second adjective is needed, it must differ from the first one. It looks like this:

[bennet@localhost asst]$ ./rndsent name: Frank Bill adj: red blue flat noun: rock tree verb: threw ate saw : Frank ate the flat red tree [bennet@localhost asst]$ ./rndsent name: Frank Bill adj: red blue flat noun: rock tree verb: threw ate saw : Frank saw the tree [bennet@localhost asst]$ ./rndsent name: Frank Bill adj: red blue flat noun: rock tree verb: threw ate saw : Frank threw the flat rock [bennet@localhost asst]$ ./rndsent name: Frank Bill adj: red blue flat noun: rock tree verb: threw ate saw : Bill saw the flat blue tree

Input Format

The input should consist of lists of words as shown above. Each list begins with a label, which must be one of name:, adj:, noun: or verb:. The input ends with a : by itself. The lists may be given an any order. The above example shows all the words on a single line, but they can be spread on multiple lines. For instance,
[bennet@localhost asst]$ ./rndsent noun: cat dog muskrat name: Alex Bill verb: saw heard liked annihilated adj: missing inebriated furry : Bill liked the missing dog [bennet@localhost asst]$ ./rndsent noun: cat dog muskrat adj: missing inebriated furry verb: saw heard liked annihilated name: Alex Bill : Alex annihilated the furry muskrat [bennet@localhost asst]$ ./rndsent verb: saw heard liked annihilated adj: missing inebriated furry noun: cat dog muskrat name: Alex Bill : Bill heard the dog

How To Proceed

I found it helpful to create a function to read in a single word list. Mine has this signature:
std::string readlist(std::vector<std::string> &vec);
It uses >> to read in a word, and adds it to the end of vec, and loops to read the entire list. Before adding each word, it checks if the word ends with a colon. If so, the loop ends, and the function returns the colon word. With this arrangement, my main program can read the first word, which will be the name of a list, and call readlist with the correct list to fill it in. Readlist will do that, and return the name of the next list. The main can then call readlist again to read the next list, and keep that up until readlist returns :, which tells the main that all the lists have been read.

So your main program will use the readlist function, called repeatedly to read in each list. Then choose and print a name at random, then a verb. Then just print the. Now, decide if you need a first adjective, and (if so), pick one at random, then decide of you need a second one, and choose and print it.

The simplest way to make sure the second differs from the first is to keep choosing until you get a different one. There are more sophisticated approaches that do not need a loop, and simply choose from the remaining words. One is to choose your second number in a range one smaller than the legal subscripts of the list. Then if the second choice matches the first, use that last item instead.

You can easily provide input from the keyboard, perhaps using copy/paste to repeat. But it can be nice to put your word lists in a file, then run the program repeatedly using the up arrow:
[bennet@localhost asst]$ ./rndsent < in.txt Alex heard the missing furry cat [bennet@localhost asst]$ ./rndsent < in.txt Jane saw the inebriated foolish cat [bennet@localhost asst]$ ./rndsent < in.txt Jane saw the inebriated foolish cat [bennet@localhost asst]$ ./rndsent < in.txt Sally liked the foolish red-tailed mouse

Random Numbers

You will need a random number generator to make choices. The simplest option is the plain-C rand function, which you can see in action here. Make sure you call srand once at the top of main. C++ provides relatively new random header, which is much more complicated and much more capable, and you can see it working here. These produce large random integers, which you can reduce to a needed range using the mod operator %. If you have a vector of words in lst, then you can choose an element at random with lst[rand()%lst.size()] or lst[randgen()%lst.size()]. When you need to make a random choice with 75% probability, you can say if(rand() % 4 < 3), or similar with randgen(). This chooses a random number which is 0, 1, 2 or 3, then tests if that number is smaller than 3. Since each number can be generated with equal probability, this is true 3 times in 4.

Submission

When your program works, submit over the web here.