Harvey Mudd College
Computer Science 42
Assignment 7, Due Monday, Oct 25, by 11:59pm

Python fun!

This week introduces you to the Python programming language through a number of fun problems.  Some of you have worked with Python before, some have not, but either way we hope that you will find these problems enjoyable. 

Problem 1: The Mandelbrot Set [30 points; individual or pair]: Submitted in a file named hw7pr1.py

Because the writeup for this problem is quite long, it's on its own page.  Click here to access it...

Problem 2: Markov Text Generation [30 points; individual]: Submitted in a file named hw7pr2.py

Submit this program as hw7pr2.py on the submission server.

Your goal in this section is to write a program that is capable of "learning" English from examples of text and then generating new "meaningful" English random text all by itself! You will accomplish this goal by writing a Markov text generation algorithm.

Here's the basic idea: English is a language with a lot of structure. Words have a tendency (indeed, an obligation) to appear only in certain sequences. Grammatical rules specify legal combinations of different parts of speech. E.g., the phrase "The cat climbs the stairs" obeys a legal word sequence. "Stairs the the climbs cat", does not. Additionally, semantics (the meaning of a word or sentence) further limits possible word combinations. "The stairs climb the cat" is a perfectly legal sentence, but it doesn't make any sense and you are very unlikely to encounter this word ordering in practice.

Even without knowing the formal rules of English, or the meaning of English words, we can get an idea of what word combinations are legal simply by looking at well-formed English text and noting the combinations of words that tend to occur in practice. Then, based on our observations, we could generate new sentences by randomly selecting words according to commonly occurring sequences of these words. For example, consider the following text:

"I love roses and carnations. I hope I get roses for my birthday."

If we start by selecting the word "I", we notice that "I" may be followed by "love", "hope" and "get" with equal probability in this text. We randomly select one of these words to add to our sentence, e.g. "I get". We can repeat this process with the word "get", necessarily selecting the word "roses" as the next word. Continuing this process could yield the phrase "I get roses and carnations". Note that this is a valid English sentence, but not one that we have seen before. Other novel sentences we might have generated include "I love roses for my birthday," and "I get roses for my birthday".

More formally, the process we use to generate these sentences is called a kth-order Markov process. A kth-order Markov process is a process where the next word depends only on the previous k words. A very special case is a first-order Markov process (when k = 1) in which the next word occurs only on the previous word.

Here's what your program must do:

The "main" trick:

In order to get your python program to start automatically, you should include a function called main() that invokes the main loop of your Markov test generator.  Then include the following line, anywhere after the definition of main:

if __name__ == "__main__" : main()

This way, the main function will start automatically when you press F5 from Idle or invoke the program at the python shell.

The text you want to use is up to you. IRS documents like this one (http://www.irs.gov/newsroom/article/0,,id=159925,00.html may be good. Random scenes from Shakespeare might also strike your fancy (http://www-tech.mit.edu/Shakespeare/). Please play with your program and try using some of your own text.  You might try your Writ001 essay!

Problem 3: Mastermind [40 points; individual or pair]: Submitted in a file named hw7pr3.py

In this problem you will be implementing a "generalized" version of the Mastermind game! First, we describe the basic functionality of this program and then, at the bottom of this page, we describe some fun optional super extra bonus parts that you might wish to do for bonus credit.

The program begins "automatically": We just include the line

if __name__ == "__main__" : main()
at the bottom of the file (anywhere after the definition of the main() function itself—this is typically at the very bottom of the file), and this automatically invokes the main() function when the program is invoked at the shell. Those long lines before and after name and main are pairs of underscore symbols: There are two consecutive underscores at the beginning and two consecutive ones at the end.

When the game begins, the program asks the player to enter:

Once the player has specified these values, the game commences. The program chooses a random "code"—the secret selection of colors in the holes. Remember that the colors are actually integers ranging from 0 to the number of colors specified by the user, minus one.

At each round of the game, the player is asked to guess the code—that is, to guess the color for each hole. The program then "scores" the player's guess. For each guess that is the correct color in the correct hole, the player gets one "black" point. Among the remaining guesses, each guess that is the correct color but in the wrong hole gets one "white" point. The score is simply the number of black points followed by the number of white points.

After each round of play, the game board is displayed. The displayed game board shows the rows that have been guessed so far along with their scores. Here is some sample input and output. Please follow these input/output conventions to make it easier for the grutors to evaluate your program. You may make minor cosmetic changes to this, but your input/output display should be essentially like this:

Welcome to Mastermind!
----------------------
How many holes per row shall we have? 3
How many rounds shall we have? 42
How many colors shall we have? 4
Enter your guess for round 0...
Enter guess for hole 0: 0
Enter guess for hole 1: 1
Enter guess for hole 2: 2
===START BOARD===
Round 0 [0, 1, 2] Score: 1 black and 1 white
====END BOARD====
Enter your guess for round 1...
Enter guess for hole 0: 0
Enter guess for hole 1: 0
Enter guess for hole 2: 2
===START BOARD===
Round 0 [0, 1, 2] Score: 1 black and 1 white
Round 1 [0, 0, 2] Score: 1 black and 2 white
====END BOARD====
Enter your guess for round 2...
Enter guess for hole 0: 0
Enter guess for hole 1: 2
Enter guess for hole 2: 0
You got it in 3 rounds!
Would you like to play again? n
Bye!

The game ends if the player guesses the score correctly (a win!) or the player has not succeeded at the end of the specified number of rounds. In either case, the player is asked if she/he would like to play again. If so, the process starts from the beginning, with the player being asked for the number of holes, rounds, and colors.

In addition to the functionality described above, your program must check to ensure that the player's input is valid. You may assume that the player will always enter a non-negative integer, but if the number of colors specified was 4 and the user guesses a color of 10, this is invalid and the user should be asked to re-enter the input.

Your program will be evaluated both for correctness and also for quality of design and style. Approximately half of your score on this problem will be based on following the good design principles discussed in lecture and summarized below. Here are a few guidelines to follow for design and style. We'll consider these guidelines in grading your code:

For the sake of debugging, you should have the following line at the top of your code:

debug = True # debug is True if debugging info is to be displayed, and False otherwise
Throughout your code, you should have conditional statements of the form if debug: print blah, blah, blah that print out key information about the inner workings of your program.

In particular, if debug is True, your program should print out the computer's chosen secret random code (the sequence of colors that you are trying to guess). This will allow you to ensure that the behavior of your program is correct. Later, of course, you can set debug to False to deactivate the printing of this information.

For example, in the game shown above, here's what things might look like in debug mode:

% python mastermind.py
Welcome to Mastermind!
----------------------
How many holes per row shall we have? 3
How many rounds shall we have? 42
How many colors shall we have? 4
DEBUG MODE: THE CODE IS [0, 2, 0]
Enter your guess for round 0...
Enter guess for hole 0: 0
Enter guess for hole 1: 1
Enter guess for hole 2: 2
DEBUG MODE: MATCH AT HOLE 0
===START BOARD===
Round 0 [0, 1, 2] Score: 1 black and 1 white
====END BOARD====


...
In addition to the observations about this problem that we made in class, here are a few things that will be of use to you:

Submit your code as hw7pr3.py. Please make sure to submit your code with debug = True so that we can see the debugging information (and particularly the secret code) when testing your program.

Totally Optional Super Fun Bonus Parts! If you want more entertainment, here are several fun optional bonus parts for you to consider:

If you add these bonus features, please submit a file called hw7pr3bonus.py and clearly document at the very top of that file what you did and how to use your program.