Software Design
Spring 2007

Homework 3

Due: Wednesday 14 February

The reading for this assignment is Chapters 7-8 of How to think....

Palindromes, Lipograms and Tautonyms

  1. Download filters.py and word_list from the usual place:

    wget http://wb/sd/code/filters.py
    wget http://wb/sd/code/word_list
    
    Read filters.py and get an idea of what it does. You should get a sense of how it works even though it uses some features we haven't seen yet.

    The function is_palindrome is an example of a filter. It checks words and indicates whether or not they are palindromes. Or, at least, it is supposed to. At the moment it indicates whether or not a word is equal to the string 'palindrome', which is probably not what we had in mind.

    If you run the program as is, it will invoke is_palindrome twice and print the results. Your job is to change is_palindrome so that it does what it is supposed to do. A palindrome, since you asked, is a word that reads the same forward and backward, like `reviver' and `noon.'

    You can solve this problem using only features we have seen in the book, like while loops and indices. If you know about other features, you are free to use them, but they are not necessary.

    Once you have your filter working, you can comment out the test code at the end of the program and uncomment the line that invokes main. Then the program will search the dictionary for palindromes.

    How many palindromes are there in the dictionary? Hint: use a pipe.

  2. Write a filter function named is_word that always returns True. Now you can run filters.py again with the new filter:

    python filters.py is_word | wc
    
    So now we know how many words there are in the dictionary.

  3. Write a filter called has_no_e that returns True if the given word doesn't have the letter `e' in it. What percentage of the words in the dictionary have no `e'?

  4. Write a function named avoids that takes a word and a string of forbidden letters, and that returns true if the word doesn't use any of the forbidden letters. You can call your function from the command line like this:

    python filters.py avoids xyz | wc
    
    Can you find a combination of 5 forbidden letters that excludes the smallest fraction of the dictionary?

  5. Write a function named uses_all that takes a word and a string of required letters, and that returns True if the word uses all the required letters at least once. How many words are there that use all the vowels aeiou? How about aeiouy?

  6. Write a function named uses_only that takes a word and a string of letters, and that returns True if the word contains only letters in the list. How many words can be formed using only the letters acefhlo? Other than `hoe alfalfa'.

  7. Write a function called is_abecedarian that returns True if the letters in a word appear in alphabetical order. How many abecedarian words are there?

Gooey

  1. Download Palindrome.py from the class web page. Read through the program and then run it. If the version of is_palindrome in your filters.py is correct, then Palindrome.py should provide a working graphical palindrome-checker.

  2. In filters.py, write a function called rotate_word that takes a string and an integer as parameters, and that returns a new string that contains the letters from the original string `rotated' by the given amount. To rotate a letter means to shift it through the alphabet, wrapping around to the beginning if necessary. For example, 'Y' shifted by 1 is 'Z', and 'Z' shifted by 1 is 'A'. 'A' shifted by 5 is 'F'.

    For you hard-drinking electrical engineers, what do you get if you rotate 'ohms' by 1? For you entrepreneurial bakers, what do you get if you rotate 'hawk' by 8? And for you environmentalists, what's 'terra' rotated by 13?

    Hint: check out the ord and chr functions documented at

    http://www.python.org/doc/current/lib/built-in-funcs.html
    

    A good solution to this problem should be appropriately general and encapsulated. It should work for upper- and lower-case letters, and for positive and negative shifts.

  3. As a JFFE, how many rotate-pairs can you find in the dictionary?

  4. As a second JFFE, go back to Palindrome.py and make a copy of check_palindrome called rotate_entry. Instead of checking for palindromes, it should take the contents of the text entry, rotate it by 1, and display the result in the label.

  5. As a third JFFE, add a second text entry to the GUI, and modify rotate_entry so that it gets the amount of the shift from the new entry.

WHAT TO TURN IN: You should hand in a copy of filters.py (printed with a2ps if possible), along with a page of plain text that presents your findings regarding words with various properties, rotate-pairs, and anything else you find that you think is interesting.