My brother introduced me to a “game” he plays while walking to work: if you see an animal, think of a person’s name for it that follows the same vowel-consonant pattern as that animal’s name. For instance, a duck has the pattern C-V-C-C, which is matched by John, among other names. This can become quite difficult for certain animals (e.g. kestrel) and some seem to strain the bounds of possibility (e.g. squirrel).
Since fun exists to be destroyed, here is some code that plays this “game” far better than any person. I’ve broken it up to add some commentary on the development.
# -*- coding: utf-8 -*- import re
re is Python's Regular Expressions module. Regexes are the obvious choice for tackling a string pattern matching problem.
vowel = '[aeiouAEIOU]' consonant = '[^aeiouAEIOU \d]' #Note: assuming y is typically a consonant, which isn't quite true - # but there's no good way to tell 'vowel y' (eg 'my') # from 'consonant y' (eg 'your') in such a simple program # To use a vowel y instead, add yY to both the above # To use y as always both a vowel and a consonant, add yY to only the first one def getVowelPattern(word): '''Returns the indices of the vowels in a word''' vwls = re.compile(vowel).finditer(word) positions =  for v in vwls: pos = v.start() positions.append(pos) return positions
We start by taking an animal name and decomposing it into a pattern of vowels and consonants, here represented by the positions of the vowels. Note that this assumes all letters are exclusively either a vowel or a consonant, which adds to the difficulty of handling 'y'.
def createPattern(vwPositions, length): '''Create a pattern to search for, from the positions of vowels in a word ''' pattern = "" for i in range(0,length): if i in vwPositions: pattern += vowel else: pattern += consonant pattern += " " return pattern
This composites a bunch of the 'vowel' and 'consonant' strings together to form a pattern matching the whole word. Fairly straightforward. This pattern will be used to search for any names matching this pattern.
def searchText(pattern, text): # Given a file of text, search for instances of the pattern p = re.compile(pattern) for line in text: m = p.match(line) if m: yield m.group() return if __name__ == "__main__": animal = raw_input("What animal are we naming? \n") vwp = getVowelPattern(animal) ptr = createPattern(vwp, len(animal)) # list of names from # http://deron.meranda.us/data/census-derived-all-first.txt with open("firstnames.txt") as f: srh = searchText(ptr, f) cont = True n = 0 while cont: n += 1 try: name = srh.next() print name if n % 3 == 0: cont = (raw_input("Continue? y/n ") == "y") except StopIteration: print "End of file reached" cont = False
We take a list of first names (male and female) sorted by population frequency, and apply the regular expression created above to find matches. Three matches are returned at a time with the option to continue or stop; this seemed like a good compromise between simplicity and the conflicting desires to see many names, to see the most common matches without scrolling through a list of results, and just to see if there's any matches at all.
Well, that was a lot of fun, and I got to find out what the two matches for 'squirrel' are.