
Mad Libs were originally invented in the 1950's, and have appeared in numerous forms over the years (see wikipedia entry).
For example, suppose the tag-a-story is as follows.
With this tag-a-story we might get any of the substitution stories below:
The lab in Compsci 6 is terrible and I love it. The lab in Compsci 6 is long and I crave it. The lab in Compsci 6 is squeamish and I despise it.You'll be using one tag-a-story to develop and debug your program, then you'll be able to use any of the stories submitted by students in generating new stories. Note that words/phrases that will be replaced are delimited by angle-brackets: < and > as shown. We call these delimited words/phrases tags in this lab.
Start out by snarfing the code for this lab, or looking at the code directory.
There are five conceptual parts to this lab.
- Reading the tag-a-story template file and extracting the tags from it (in the order they appear).
- Substituting user-entered (first) and then auto-generated (later) words/phrases for each tag read so that a story can be auto-generated --- you'll essentially replace each tag by an auto-generated substitute.
- Create a dictionary of substitutions for each tag by reading the file word_lists.txt whose format is described below.
- Print the auto-generated story with a specified line-width, e.g., 50 characters per line or 80 per line and so on.
- (if time) Allow the user to choose a tag-a-story template from the web and/or allow the user to substitute her own replacements for each tag rather than having the substitutions auto-generated.
Complete the lab by following the steps below. Each step is accompanied by questions you should answer on the handin page -- be sure to answer these questions!
-
First you'll add code to the function
do_mad_lib
so that the user can choose a replacement for each tag in the listall_tags
. When you snarf and run the program at first, it prints this as the value of the local variableall_tags
indo_mad_lib
:['adjective' 'food']
You should write code so that a new list is created and assigned to the local variablesubs
that replaces each tag with a user-entered response. You can do this with a list comprehension by calling the functionget_word_from_user
with each tag as a parameter. When you've created this list and printed bothall_tags
and and the new listsubs
you're ready for step two.Handin Questions
- Create a string using the list
subs
, the stringtemplate
and the string format operator % by adding this single line and printing the value ofstory
.story = template % tuple(subs)
Here you are using the
%
operator to do some string formatting. Given a stringstory
that contains some "%s" substrings within it, and given a tupletup
with the same number of elements as there are "%s"'s instory
, the expressionstory % tup
substitutes each element oftup
intostory
for the corresponding instance of "%s". To make this concrete, the expression"Insert something %s and something else %s" % ("here", "over here")
"Insert something here and something else over here"
.Handin Questions
-
Entering a phrase for each tag is time-consuming and
auto-generated stories can be fun. To do this, we'll need a
way to supply words that match a given description. This is
supplied for you in the file
word_lists.txt
, but we need to parse it into a useful format.Complete the function
read_tagstore
which will add tags and replacements to a dictionary and return it. In the dictionary keys are strings representing tags (word/phrase), and the key's corresponding value is a lists of strings that will be substituted for the key. For example:adjective: awesome, boring, stupid, amazing, fantastic, confusing, silly, big, yellow animal: dog, cat, human, lion, pony, squirrel
Note that each tag is separated from replacements by a colon character and replacements are comma-separated (you'll need to use the string .split method twice). In the fileword_lists.txt
a tag can occur multiple times, e.g., on different lines. This means if the key is already in the dictionary you'll need to add strings to its list (use the list .extend method).When you've read the file and created the dictionary, be sure to print it to verify that you read the file correctly, then remove or comment-out the print statements.
Handin Questions
- To test that the dictionary was created properly you
can replace the function
get_word_from_user()
you used in the first part of lab withget_word_from_computer()
which uses the global dictionary_tagstore
. Make that change indo_mad_lib
. Then make the function used to get replacements for tags a parameter passed todo_mad_lib
. Add a new parameter to the function, namedtag_getter
, which will be the function used to get words to replace each tag in the story -- pass the argumentget_word_from_computer
(no parentheses) when you calldo_mad_lib
.This kind of modification (changing prevously written code to be more general, extensible, efficient, or elegant) is called a "refactoring." Software engineers refactor code all the time, because it makes code easier to use in the future.
Handin Questions
- Rather than printing the story on a single line,
complete
the function
print_out
that has been started in the program. You'll need to add two lines, though you can add more. You'll also need to change the lineprint word
so that it prints a word and a space and stays on the same line. Each line you add updates the value of local variablecurr_len
so that it represents the number of characters printed on the current line. If you update the value twice, the function should work correctly -- call it fromdo_mad_lib
to print the completed story. The idea is to print each word in story one-at-a-time (with a space after it), but if printing the word would cause more than line_width characters to be printed on a line, start a new line.Handin Questions
- You should write your own tag-a-story/Mad Lib and upload it to
this
site:
http://www.cs.duke.edu/csed/tag-a-story/upload/. Pick a category and
upload your file. You can verify that the file was uploaded by
running the program
URLreader.py
and choose the file you uploaded. -
If there is extra time, try to use the combine the functionality of the
URLreader.py
module with theMadLibs.py
module to generate a story from a URL.