Rhyme / app.py
JaeSwift's picture
Create app.py
e0171fd verified
raw
history blame
4.14 kB
import pronouncing
import string
import copy
import sys
CONSONANTS = set(string.ascii_uppercase)-set('AEIOU')
def get_phones(word):
"""
Given a user-inputted word, return phones, its corresponding list of phonemes.
For example, the input guitar yields the list ['G', 'IH0', 'T', 'AA1', 'R']
"""
phones_for_word = pronouncing.phones_for_word(word)
if not phones_for_word:
return None
phones = phones_for_word[0].split()
return phones
def _get_vowel_index(phones):
"""
In preparation to search for slant rhymes, return the position of the first vowel in phones.
"""
for index, phone in enumerate(phones):
if phone[0] in 'AEIOU':
return index
def _get_consonant_indices(phones):
"""
In preparation to search for slant rhymes, return the positions of all intermediate consonants after the first vowel in phones.
"""
indices = []
for index, phone in enumerate(phones):
if phone[0] in CONSONANTS and index < len(phones) - 1:
indices.append(index)
return indices
def _get_rhyming_tail(phones):
"""
In preparation to search for multisyllabic rhymes, remove characters before the first vowel in phones.
For example, phones changes from ['G', 'IH0', 'T', 'AA1', 'R'] to ['IH0', 'T', 'AA1', 'R']
"""
index = _get_vowel_index(phones)
return phones[index:]
def _slant_rhyme_consonants(phones):
"""
Replaces intermediate consonants with a period, the wildcard character. The final consonant is preserved.
For example, replace the intermediate 'T' in ['IH0', 'T', 'AA1', 'R'], leaving ['IH0', '.', 'AA1', 'R']
"""
consonant_indices = _get_consonant_indices(phones)
new_phones = copy.copy(phones)
for index in consonant_indices:
new_phones[index] = '.'
return new_phones
def get_perfect_rhymes(phones):
"""
Given phones, search for perfect, multisyllabic rhymes with no syllables afterwards.
"""
rhyming_tail = " ".join(_get_rhyming_tail(phones))
return pronouncing.search(rhyming_tail + "$")
def get_internal_rhymes(phones):
"""
Given phones, search for internal, multisyllabic rhymes.
"""
rhyming_tail = " ".join(_get_rhyming_tail(phones))
return pronouncing.search(rhyming_tail)
def get_slant_rhymes(phones):
"""
Given phones, return all slant and internal rhymes.
Slant rhymes do not require matching consonants before the final position. For example, guitar and cigar.
Internal rhymes do not require the matching syllables to be final. For example, guitar and departure.
"""
tail = _get_rhyming_tail(phones)
search = ' '.join(_slant_rhyme_consonants(tail))
return pronouncing.search(search)
def main(word):
"""
Search for slant rhymes given word, an argument from the command line.
For an inputted word not recognized in the CMU dictionary, prompt user to try another word.
"""
phones = get_phones(word)
if phones is None:
print('That word is not recognized. Please check the spelling and avoid proper nouns.')
exit(1)
perfect_rhymes = get_perfect_rhymes(phones)
internal_rhymes = get_internal_rhymes(phones)
slant_rhymes = get_slant_rhymes(phones)
perfects_without_word = set(perfect_rhymes) - {word}
internals_without_perfects = set(internal_rhymes) - set(perfect_rhymes) - {word}
imperfect_slants = set(slant_rhymes) - set(internal_rhymes) - {word}
if perfects_without_word:
print('Perfect rhymes:', ", ".join(sorted(perfects_without_word)), '\n')
else:
print('No perfect rhymes.\n')
if internals_without_perfects:
print('Internal rhymes:', ", ".join(sorted(internals_without_perfects)), '\n')
else:
print('No internal rhymes.\n')
if imperfect_slants:
print('Slant rhymes:', ", ".join(sorted(imperfect_slants)))
else:
print('No slant rhymes.')
if __name__ == '__main__':
if len(sys.argv) < 2:
print('Usage: multisyllabic_rhymer.py word, where word is the rhyme target.')
exit(1)
main(sys.argv[1])