Poetry Form Checker Solution

Limericks, sonnets, haiku, and other forms of poetry each follow prescribed patterns that give the number of lines, the number of syllables on each line, and a rhyme scheme. For example, limericks are five lines long; the first, second, and fifth lines each have eight syllables and rhyme with each other; and the third and fourth lines each have five syllables and rhyme with each other. (There are additional rules about the location and number of stressed vs. unstressed syllables, but we'll ignore those rules for this assignment.) 
Here is a stupendous work of limerick art:
 
    I wish I had thought of a rhyme
    Before I ran all out of time!
    I'll sit here instead,
    A cloud on my head
    That rains 'til I'm covered with slime.
We're sure that you've all kept yourselves awake wondering if there was a way to have a computer program check whether a poem is a limerick or if it follows some other poetry pattern. Here's your chance to resolve the question!
 
The CMU Pronouncing Dictionary
 
The Carnegie Mellon University Pronouncing Dictionary describes how to pronounce words. Head there now and look up a couple of words; try searching for words like "Daniel", "is", and "goofy", and see if you can interpret the results. Do contractions like "I'll" (short for "I will") and "we'll" (short for "we will") work? Try clicking the "Show Lexical Stress" checkbox too, and see how that changes the result.
 
Here is the output for "Daniel" (with "Show Lexical Stress" turned on): D AE1 N Y AH0 L. Each of the separate pieces describes a sound; these pieces are called phonemes. The phonemes are either vowel sounds or consonant sounds, and they are from a project called Arpabet that was created by the Advanced Research Projects Agency (ARPA) back in the 1970's. The vowel phonemes all have a number after them; these indicate a level of stress. For example, in "Daniel", the stress falls on the first vowel, AE1, and the second vowel is unstressed, AH0. The higher the level of stress, the larger the number after the vowel phoneme. In the CMU Pronouncing Dictionary, stress is always on a vowel sound.
 
Your program will read the file dictionary.txt, which is our version of the Pronouncing Dictionary. You must use this file, not any files from the CMU website. Take a look at our dictionary.txt file to see the format; notice that any line beginning with ;;; is a comment and not part of the dictionary.
 
Notice that the words in dictionary.txt are all uppercase and that they do not contain surrounding punctuation. When your program looks up a word, use the uppercase form, with no leading or trailing punctuation. Function clean_up in the starter code file poetry_functions.py will be be helpful here.
 
Poetry Form Descriptions
 
For each type of poetry form (limerick, haiku, etc.), we will write its rules as a poetry form description. For example, at the beginning of this handout, we gave the rules for what it means to be a limerick. Here's our poetry form description for the limerick poetry form:
 
    8 A
    8 A
    5 B
    5 B
    8 A
On each line, the first piece of information is a number that indicates the number of syllables required on that line of the poem. The second piece of information is a letter that indicates the rhyme scheme. Here, lines 1, 2, and 5 must rhyme with each other because they're all marked with the same letter (A), and lines 3 and 4 must rhyme with each other because they're both marked with the same letter (B).
 
Some poetry forms don't require lines that rhyme. For example, a haiku has 5 syllables in the first line, 7 in the second line, and 5 in the third line, but there are no rhyme requirements. Here is an example:
 
    Dan's hands are quiet.
    Soft peace surrounds him gently:
    No thought moves the air.
And another one:
 
    Jen sits quietly,
    Thinking of assignment three.
    All ideas bad.
We'll indicate the lack of a rhyme requirement by using the symbol *. Here is our poetry form description for the haiku poetry form:
 
    5 *
    7 *
    5 *
Some poetry forms have rhyme requirements but don't have a specified number of syllables per line. Quintain (English) is one such example; these are 5-line poems with an ABABB rhyme scheme, but with no syllabic requirements. Here is our poetry form description for the Quintain (English) poetry form (notice that the number 0 is used to indicate that there is no requirement on the number of syllables in the line):
 
    0 A
    0 B
    0 A
    0 B
    0 B
Here's an example of a Quintain (English) from Percy Bysshe Shelly's Ode To A Skylark:
 
    Teach us, Sprite or Bird,
    What sweet thoughts are thine:
    I have never heard
    Praise of love or wine
    That panted forth a flood of rapture so divine.
Your program will read a poetry form description file containing poetry form names and descriptions. For each poetry form in the file, the first line gives the name of the poetry form, and subsequent lines contain the number of syllables and rhyme scheme as described in this section. Each poetry form is separated from the next by a blank line. We have provided poetry_forms.txt as an example poetry form description file. (We will test with other poetry form descriptions as well.) You may assume that the poetry form names given in a poetry form description file are all different.
 
The poetry samples given in this assignment description, as well as some other poems, are posted on the Poetry Files webpage.
 
Data Representation
 
Poetry Pattern
 
A poetry pattern is our data structure for a poetry form description. It is a two-item tuple of:
a list of the number of syllables per line (a list of int)
the rhyme scheme (a list of str)
For example, here is the poetry pattern for a limerick:
 
([8, 8, 5, 5, 8], ['A', 'A', 'B', 'B', 'A'])
Pronunciation Dictionary
 
A pronunciation dictionary is our data structure for mapping words to phonemes. It is a dict of {str: list of str}, where:
each key is a word (a str)
each value is a list of phonemes for that word (a list of str)
For example, here is a (very tiny) pronunciation dictionary:
 
{'DANIEL': ['D', 'AE1', 'N', 'Y', 'AH0', 'L'], 
 'IS': ['IH1', 'Z'], 
 'GOOFY': ['G', 'UW1', 'F', 'IY0']}
Valid Input
 
For all poetry used for this assignment, you may assume that all words in the poetry will appear as keys in the pronunciation dictionary that is being used.
 
Required Functions
 
In the starter code file poetry_functions.py, complete the following function definitions. In addition, you must add some helper functions to aid with the implementation of these required functions.
 
The main program
 
We have provided the main program file poetry_program.py which is complete and must not be changed. Place the poetry_program.py file in the same folder (directory) as your poetry_functions.py and poetry_reader.py files. Once you have correctly implemented the functions in poetry_functions.py and poetry_reader.py, execution of the main program will:
 
Read our version of the CMU Pronouncing Dictionary (dictionary.txt)
Read poetry_forms.txt
Repeatedly ask the user for a poetry form to check and the name of a file containing a poem. The program will report on whether or not the poem satisfies the poetry form description for the chosen poetry form.
Required Testing (unittest)
 
Write (and submit) a set of unittests for functions count_lines and check_syllables. Name these two files test_count_lines.py and test_check_syllables.py. For each test method, include a brief docstring description specifying what is being tested. For unittest methods, the docstring description should not include a type contract or example calls.
 
a3_type_checker.py and doctest
 
a3_type_checker.py
 
We are providing a type-check module that can be used to test whether your functions in poetry_functions.py have the correct parameter and return types. To use the type checker, place a3_type_checker.py in the same folder (directory) as your poetry_functions.py and run it.
 
If the type-checks pass: the output will consist only of one thing: the word "okay". This means that the function parameters and return types match the assignment specification.
 
If the type-checks fail: Look carefully at the message provided. One or more of your parameter or return types does not match the assignment specification. Fix your code and re-run the tests. Make sure the tests pass before submitting.
 
doctest
 
Each function in poetry_functions.py has a doctest test in its docstring description. Be sure to run the doctests and make sure that they pass. With the functions in this assignment, there are many more possible cases to test (and cases where your code could go wrong). If you want to get a great mark on the correctness of your functions, do a great job of testing your functions under all possible conditions. Then we won't be able to find any errors that you haven't already fixed!
 
You may have noticed that there is an r before each of the opening docstring triple-quotes in the poetry_functions.py starter code. The r denotes a raw string and means that special characters like \ will not be treated as special. By using raw strings for doctests that include \n and other escape sequences, the docstrings will be runnable as doctests.
 
 four files in zip:
 
poetry_reader.py
poetry_functions.py
test_count_lines.py
test_check_syllables.py
Powered by