| Project #1 | CMSC 389C |
| Due: Friday 1/13 at 11:00PM | C++ Programming |
Markov Chain Random Text Generation

Objective
We'll have some fun practicing strings and vectors in C++. We'll also be practicing how different kinds of variables can be used as parameters.
Overview
We will create a program that will generate random text. The goal is for the text to resemble (at least somewhat) text written by a human. We will rely on a mathematical construct known as Markov Chains. This is not a new idea... unfortunately spammers frequently use these kinds of techniques to generate random email messages that appear as though they may have been written by humans. This will frequently fool spam filters into believing they are legitimate messages instead of junkmail! Of course there are also other, more constructive applications of Markov Chain Random Text Generation!The idea behind the technique is to begin by having the program read in a large body of text, written by a human. The program will record chains of words of a fixed length, and will keep track of which particular word appeared immediately after each chain. This information is then used by a very simple algorithm that generates random text. We'll describe the process fully, below.
To give us something to work with, let's pretend the the following text is the input to the program:
THE DOG IS YELLOW THE CAT IS YELLOW SO IS THE DOG THE CAT
The program will begin by collecting all of the "chains" of words for a fixed length. Here are the chains that the program would store for several different potential "lengths". After each chain, we record the word that immediately followed the chain in the original passage:
| length 1 | length 2 | length 3 |
|
[THE] DOG [DOG] IS [IS] YELLOW [YELLOW] THE [THE] CAT [CAT] IS [IS] YELLOW [YELLOW] SO [SO] IS [IS] THE [THE] DOG [DOG] THE [THE] CAT [CAT] THE_END |
[THE, DOG] IS [DOG, IS] YELLOW [IS, YELLOW] THE [YELLOW, THE] CAT [THE, CAT] IS [CAT, IS] YELLOW [IS, YELLOW] SO [YELLOW, SO] IS [SO, IS] THE [IS, THE] DOG [THE, DOG] THE [DOG, THE] CAT [THE, CAT] THE_END |
[THE, DOG, IS] YELLOW [DOG, IS, YELLOW] THE [IS, YELLOW, THE] CAT [YELLOW, THE, CAT] IS [THE, CAT, IS] YELLOW [CAT, IS, YELLOW] SO [IS, YELLOW, SO] IS [YELLOW, SO, IS] THE [SO, IS, THE] DOG [IS, THE, DOG] THE [THE, DOG, THE] CAT [DOG, THE, CAT] THE_END |
Notice that we invented a terminal symbol "THE_END" to denote the end of the original passage.
Study the table above and make sure you understand how it was generated before you read further!
The program will actually store the data a bit more efficiently. Some of the chains appear more than once, so rather than storing duplicate chains, we will store each kind of chain just once, along with a list of the various endings that were seen in the original text after that kind of chain:
| length 1 | length 2 | length 3 |
|
[THE] {DOG, CAT, DOG, CAT} [DOG] {IS, THE} [IS] {YELLOW, YELLOW, THE} [YELLOW] {THE, SO} [CAT] {IS, THE_END} [SO] {IS} |
[THE, DOG] {IS, THE} [DOG, IS] {YELLOW} [IS, YELLOW] {THE, SO} [YELLOW, THE] {CAT} [THE, CAT] {IS, THE_END} [CAT, IS] {YELLOW} [YELLOW, SO] {IS} [SO, IS] {THE} [IS, THE] {DOG} [DOG, THE] {CAT} |
[THE, DOG, IS] {YELLOW} [DOG, IS, YELLOW] {THE} [IS, YELLOW, THE] {CAT} [YELLOW, THE, CAT] {IS} [THE, CAT, IS] {YELLOW} [CAT, IS, YELLOW] {SO} [IS, YELLOW, SO] {IS} [YELLOW, SO, IS] {THE} [SO, IS, THE] {DOG} [IS, THE, DOG] {THE} [THE, DOG, THE] {CAT} [DOG, THE, CAT] {THE_END} |
Study the table above and make sure you understand how it was generated before you read further!
We will now describe how the data structure above can be used to create a randomly generated passage! Let's use chains of length two, so focus your attention on the center column from the table above.
We start with the first chain (of length 2) that appeared in the original text:
THE DOGNow we have to choose a single word to follow this chain. We look up this chain in the table, and find that there are two choices for a following word: "IS" or "THE". We use a random number generator to pick. Let's suppose it chooses the second one (THE). Now we have:
THE DOG THEWe now take the ending chain [DOG, THE] and look for a word to follow it. According to the chart, there is only one choice: CAT. So now we have:
THE DOG THE CATWe now take the chain [THE CAT] and look for a word to follow it. We have two choices (IS, or THE_END) and so we choose one randomly. Let's suppose we choose the second one, "THE_END". Now we have:
THE DOG THE CAT THE_ENDWe stop now, since we encountered the terminal symbol "THE_END".
Let's consider another example. This time we'll use chains of length 1. We start with the first chain from the original text:
THEWhen we look up the chain [THE] in the chart, we see that we have a list of four things (some repeats) to choose from. We use a random number to choose an index from 0 to 3. Let's suppose it gives us 3, which corresponds to CAT. Now we have:
THE CATNow we look up the chain [CAT] in the chart. Two possible endings: IS or THE_END. Let's suppose we randomly choose IS:
THE CAT ISLooking up IS, we see three possible endings. We use a random number generator to give us a value from 0 to 2. Let's suppose it gives us 2:
THE CAT IS THENext we look up the chain [THE]. Again, the random number generator gives us a value from 0 to 3. Let's pretend it is 1:
THE CAT IS THE CATNow looking up [CAT], we see two possible endings, IS or THE_END. Let's imagine we select the second one, so that the final passage is:
THE DOG IS THE CAT THE_END
Data Structures
During a particular run of the program, the length of the chains will remain fixed. We must read some words as input, and then construct data structures as depicted above for that particular chain size.
A "chain" will be stored as a vector of strings.
A "list of endings" will also be stored as a vector of strings.
We will use "parallel vectors" to store the list of chains and their corresponding endings. In other words, we will use a vector<vector<string>> to store all of the chains and we will use a vector<vector<string>> to store the corresponding endings.
For example, suppose the chain length is currently 2, and we use the example above as our input. We will construct two big vectors:
endings will be a vector<vector<string>>
containing the 9 corresponding "ending lists" (each of which is a vector of
strings):
[[IS, THE], [YELLOW], [THE, SO], [CAT], [IS, THE_END], [YELLOW], [IS], [THE], [DOG], [CAT]}
Syntax Hint
The g++ compiler is very fussy about spacing when you compose templates. Instead of typing:Getting the Project Files
Login to the grace system. Go into the course directory; go into the "student" directory, and from there go into your own personal directory. Once you are in your own directory, type:driver.cpp
Here we have given you a main function that you can compile with your code to try it out. This main function is not being used for any testing, so feel free to modify it if you want.Sample Input Files
You can run the driver with just about any text file, but we have provided two text files for you to play around with:textGenerator.cpp
You will be adding code to a file called TextGenerator.cpp. You will see that the following function has already been written for you. DO NOT MODIFY IT!
You may write as many functions as you want, but you must include the following functions:
createDataStructures(originalWords, chains, endings, CHAIN_SIZE);Notes:
generateRandomText(chains, endings, CHAIN_SIZE);Notes:
int index = rand() % 4; // index will be in the range 0 to 3Failure to follow this procedure will result in failing all of the tests!
textGenerator.h
Be sure to update the file textGenerator.h so that it includes function prototypes for the two functions that you are writing. These are part of the API for this module, so it is important to include their prototypes in the header file. (You do not need to include prototypes for other functions you have written, since they are not part of the API -- they are like "private" methods in Java.)Using the Makefile (Provided)
As discussed previously, to build an executable program that will generate random text using your code, type:Submitting
Have fun!