The purpose of this assignment is to give you practice with dictionaries, text files, working with existing code, and making design decisions.
(Thanks to Raja Sooriamurthi for his help in preparing this part.) In this part of the assignment, you'll write a little "heads or tails" game, where the computer tries to predict what the user will choose next. It does this by relying on what the user has done in similar situations earlier in the game. Once the computer makes a prediction, the user is asked for their next choice (heads or tails). If the computer made a correct prediction, it receives a point; if not, the user receives a point. Whoever reaches the specified number of points first is deemed to be the winner. Here is a sample game transcript, showing how the game works (and showing that the computer took me to school on this one).
In order to make the prediction, the computer takes into account the last four choices the user made. We call these last four choices the current context. For example, the last four choices could be h, h, t, t, representing the situation where the last four choices made by the user were heads, heads, tails, and (most recently) tails. The assumption is that the user will do something predictable at this point, based on what they have done in the past when their previous four choices were the same as they are now. For example, imagine that when the last four choices have been h, h, t, t, the user has chosen heads ten times and tails just twice. The computer will guess heads here, since it occurs more often than tails under this context.
The game maintains two important data structures. A context
is a string, always of length 4. It begins as the string "****", representing the fact that the user has made no guesses. Via the function shift
, new user guesses are added to the right, pushing older guesses to the left. The other data structure, which we call memory
, is a dictionary. Its keys are contexts (i.e. strings of length 4), and its values represent the number of heads and tails that the user has picked so far under that context. It is up to you to decide how best to store these values.
Download the starter code for this question. You are given the function play
, which is the entry point for the game. It calls other functions to carry out sub-tasks, which you must write according to their docstrings. When you have written all of the functions that contain pass
, you should be able to play the game. Do not (I mean it! ;)) modify the existing code! The goal is to treat the current code as a framework, which you complete by inserting your functions. Save your solution in file mindreader.py
.
Some of your instructors are lazy. (Present company naturally excluded.) To create your tests and exams, they might use software that randomly selects questions from a prefabricated question bank. These question banks come as part of "instructor resources" for the chosen course textbook. They often include hundreds of questions of various types, such as multiple choice, true/false, short answer, fill-in-the-blank, and so on. In this part of the assignment, you'll write a program that takes a question bank of multiple choice and true/false questions, and randomly selects a user-specified number of each type of question. It will write these questions to a text file, so your lazy instructor can simply print that file and give you your test. It also outputs an answer key (to a different file), to help your lazy instructor mark the test when the time comes.
To understand the format of a question bank, it may help to look at a sample question bank. Question banks consist of zero or more multiple choice questions, and zero or more true/false questions. They may be interleaved in any order; notice that the sample question bank contains multiple choice (MC) and true/false (TF) questions interspersed.
A multiple choice question consists of the following:
MC
A true/false question consists of the following:
TF
T
or F
, immediately followed by the text of the true/false question itself. The first character indicates whether the correct answer is true or false
Your program must read the question file only once. While reading the file, its data should be stored in Python objects so that you can later use it when randomly choosing questions.
Your program should operate in the following steps.
Here is a complete example of program execution.
File of questions? questions.txt There are 5 multiple choice questions. Use how many? 2 There are 4 true/false questions. Use how many? 3 Name of test file to write? exam.txt Name of answer key file to write? exam_answers.txtAs evinced above, the user has chosen to use this questions.txt question file. The user has also specified that the program should generate a exam.txt test and this exam_answers.txt answer key. Of course, the program randomly selected the questions; if you use exactly the same parameters, your resultant test will differ each time you run the program. Save your solution as file
lazy_exam.py
. You should have an if __name__ == '__main__':
block that acts as the entry point to your program; your code should start running when we click Run in Wing.
This is the first time in the course that I haven't decomposed a larger program into smaller functions. It's your turn to do this! You should use functions to divide your program into meaningful pieces, and to prevent code duplication. Part of your grade will reflect how well you design your program. One approach might be to start by describing in English the steps that are carried out by the main program. Some of these steps may be simple enough to describe as one or two lines of Python. Others will require more code, and are prime candidates to be wrapped as functions. You can tackle each function the same way: describe its behavior in English, creating helper functions for the steps that are repeated throughout the program, or are complex enough to stand on their own as useful functions.
These are the aspects of your work that we will focus on in the marking:
Hand in the following files:
mindreader.py
lazy_exam.py