Check for iambic pentameter?

Question:

I am kind of stuck on a question that I have to do regarding iambic pentameters, but because it is long, I’ll try to simplify it.
So I need to get some words and their stress patterns from a text file that look somewhat like this:

if, 0
music,10
be,1
the,0
food,1
of,0
love,1
play,0
on,1
hello,01
world,1

And from the file, you can assume there will be much more words for different sentences. I am trying to get sentences from a text file which have multiple sentences, and to see if the sentence (ignoring punctuation and case) is an iambic pentameter.

For example if the text file contains this:

If music be the food of love play on
hello world

The first sentence will be assigned from the stress dictionary like this: 0101010101, and the second is obviously not a pentameter(011). I would like it so that it only prints sentences which are iambic pentameters.

Sorry if this is a convoluted or messy question.
This is what I have so far:

import string
dict = {};
sentence = open('sentences.txt')
stress = open('stress.txt')
for some in stress:
  word,number = some.split(',')
  dict[word] = number
for line in sentence:
  one = line.split()
Asked By: Hjekien

||

Answers:

I wouldn’t have thought iambic pentameter was that clear cut: always some words end up getting stressed or unstressed in order to fit the rhythm. But anyway. Something like this:

for line in sentences:
    words = line.split()
    stresspattern = ''.join([dict[word] for word in words])
    if stresspattern=='0101010101':
         print line

By the way, it’s generally a bad idea to be calling your dictionary ‘dict’, since you’re hiding the dict type.

Answered By: khelwood

I don’t think you are building your dictionary of stresses correctly. It’s crucial to remember to get rid of the implicit n character from lines as you read them in, as well as strip any whitespace from words after you’ve split on the comma. As things stand, the line if, 0 will be split to ['if', ' 0n'] which isn’t what you want.

So to create your dictionary of stresses you could do something like this:

stress_dict = {}

with open('stress.txt', 'r') as f:
    for line in f:
        word_stress = line.strip().split(',')
        word = word_stress[0].strip().lower()
        stress = word_stress[1].strip()
        stress_dict[word] = stress

For the actual checking, the answer by @khelwood is a good way, but I’d take extra care to handle the n character as you read in the lines and also make sure that all the characters in the line were lowercase (like in your dictionary).

Define a function is_iambic_pentameter to check whether a sentence is an iambic pentameter (returning True/False) and then check each line in sentences.txt:

def is_iambic_pentameter(line):
    line_stresses = [stress_dict[word] for word in line.split()]
    line_stresses = ''.join(line_stresses)
    return line_stresses == '0101010101'

with open('sentences.txt', 'r') as f:
    for line in f:
        line = line.rstrip()
        line = line.lower()
        if is_iambic_pentameter(line):
            print line

As an aside, you might be interested in NLTK, a natural language processing library for Python. Some Internet searching finds that people have written Haiku generators and other scripts for evaluating poetic forms using the library.

Answered By: Alex Riley

Here’s how the complete code could look like:

#!/usr/bin/env python3
def is_iambic_pentameter(words, word_stress_pattern):
    """Whether words are a line of iambic pentameter.

    word_stress_pattern is a callable that given a word returns
    its stress pattern
    """
    return ''.join(map(word_stress_pattern, words)) == '01'*5

# create 'word -> stress pattern' mapping, to implement word_stress_pattern(word)
with open('stress.txt') as stress_file:
    word_stress_pattern = dict(map(str.strip, line.split(','))
                               for line in stress_file).__getitem__

# print lines that use iambic pentameter
with open('sentences.txt') as file:
    for line in file:
        if is_iambic_pentameter(line.casefold().split(), word_stress_pattern):
            print(line, end='')
Answered By: jfs
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.