What You Say?
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.