patternpythonMinor
CarTalk's Homophones Puzzler: A Programmatic Solution
Viewed 0 times
cartalkhomophonesprogrammaticsolutionpuzzler
Problem
The puzzler:
This was sent in by a fellow named Dan O'Leary. He came upon a common
one-syllable, five-letter word recently that has the following unique
property. When you remove the first letter, the remaining letters form
a homophone of the original word, that is a word that sounds exactly
the same. Replace the first letter, that is, put it back and remove
the second letter and the result is yet another homophone of the
original word. And the question is, what's the word?
Now I'm going to give you an example that doesn't work. Let's look at
the five-letter word, 'wrack.' W-R-A-C-K, you know like to 'wrack with
pain.' If I remove the first letter, I am left with a four-letter
word, 'R-A-C-K.' As in, 'Holy cow, did you see the rack on that buck!
It must have been a nine-pointer!' It's a perfect homophone. If you
put the 'w' back, and remove the 'r,' instead, you're left with the
word, 'wack,' which is a real word, it's just not a homophone of the
other two words.
I've used CMU Pronouncing Dictionary and modified it (manually) to keep alphabetical strings only.
My code:
```
def read_dict(file_path):
"""Reads 'CMU Pronouncing Dictionary' text file.
returns: dict mapping from a word to a string describing
its pronounciation
file_path: str
"""
fin = open(file_path)
pron_dict = {}
for line in fin:
index = line.find(' ') # e.g. "AA EY2 EY1"
word = line[:index]
pron = line[index+2:]
pron_dict[word] = pron
return pron_dict
def are_homophones(pron_dict, word1, word2, word3):
"""Returns whether 3 words are homophones.
pron_dict: dict
"""
for word in [word1, word2, word3]:
if not word in pron_dict:
return False
return pron_dict[word1] == pron_dict[word2] == pron_dict[word3]
def find_homophones_words(pron_dict):
"""Returns a list of words, where:
* word
* word with the first item omitted
This was sent in by a fellow named Dan O'Leary. He came upon a common
one-syllable, five-letter word recently that has the following unique
property. When you remove the first letter, the remaining letters form
a homophone of the original word, that is a word that sounds exactly
the same. Replace the first letter, that is, put it back and remove
the second letter and the result is yet another homophone of the
original word. And the question is, what's the word?
Now I'm going to give you an example that doesn't work. Let's look at
the five-letter word, 'wrack.' W-R-A-C-K, you know like to 'wrack with
pain.' If I remove the first letter, I am left with a four-letter
word, 'R-A-C-K.' As in, 'Holy cow, did you see the rack on that buck!
It must have been a nine-pointer!' It's a perfect homophone. If you
put the 'w' back, and remove the 'r,' instead, you're left with the
word, 'wack,' which is a real word, it's just not a homophone of the
other two words.
I've used CMU Pronouncing Dictionary and modified it (manually) to keep alphabetical strings only.
My code:
```
def read_dict(file_path):
"""Reads 'CMU Pronouncing Dictionary' text file.
returns: dict mapping from a word to a string describing
its pronounciation
file_path: str
"""
fin = open(file_path)
pron_dict = {}
for line in fin:
index = line.find(' ') # e.g. "AA EY2 EY1"
word = line[:index]
pron = line[index+2:]
pron_dict[word] = pron
return pron_dict
def are_homophones(pron_dict, word1, word2, word3):
"""Returns whether 3 words are homophones.
pron_dict: dict
"""
for word in [word1, word2, word3]:
if not word in pron_dict:
return False
return pron_dict[word1] == pron_dict[word2] == pron_dict[word3]
def find_homophones_words(pron_dict):
"""Returns a list of words, where:
* word
* word with the first item omitted
Solution
There's an efficiency improvement you could make to
It's also good practice to use
are_homophones: As is, you check that all three words are in pron_dict before checking that they're the same. However, it's better practice to catch errors using try blocks rather than trying to prevent them from happening (see this Stack Overflow post). A cleaner/faster way way to write this would be def are_homophones(pron_dict, word1, word2, word3):
try:
return pron_dict[word1] == pron_dict[word2] == pron_dict[word3]
except KeyError:
return FalseIt's also good practice to use
with blocks to open files so that Python automatically handles closing the file. With this change, read_dict becomesdef read_dict(file_path):
pron_dict = {}
with open(file_path) as fin:
for line in fin:
index = line.find(' ') # e.g. "AA EY2 EY1"
word = line[:index]
pron = line[index+2:]
pron_dict[word] = pron
return pron_dictCode Snippets
def are_homophones(pron_dict, word1, word2, word3):
try:
return pron_dict[word1] == pron_dict[word2] == pron_dict[word3]
except KeyError:
return Falsedef read_dict(file_path):
pron_dict = {}
with open(file_path) as fin:
for line in fin:
index = line.find(' ') # e.g. "AA EY2 EY1"
word = line[:index]
pron = line[index+2:]
pron_dict[word] = pron
return pron_dictContext
StackExchange Code Review Q#139395, answer score: 7
Revisions (0)
No revisions yet.