JaeSwift commited on
Commit
e0171fd
·
verified ·
1 Parent(s): 159877a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +141 -0
app.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pronouncing
2
+ import string
3
+ import copy
4
+ import sys
5
+
6
+
7
+ CONSONANTS = set(string.ascii_uppercase)-set('AEIOU')
8
+
9
+
10
+ def get_phones(word):
11
+ """
12
+ Given a user-inputted word, return phones, its corresponding list of phonemes.
13
+
14
+ For example, the input guitar yields the list ['G', 'IH0', 'T', 'AA1', 'R']
15
+ """
16
+ phones_for_word = pronouncing.phones_for_word(word)
17
+
18
+ if not phones_for_word:
19
+ return None
20
+
21
+ phones = phones_for_word[0].split()
22
+ return phones
23
+
24
+
25
+ def _get_vowel_index(phones):
26
+ """
27
+ In preparation to search for slant rhymes, return the position of the first vowel in phones.
28
+ """
29
+ for index, phone in enumerate(phones):
30
+ if phone[0] in 'AEIOU':
31
+ return index
32
+
33
+
34
+ def _get_consonant_indices(phones):
35
+ """
36
+ In preparation to search for slant rhymes, return the positions of all intermediate consonants after the first vowel in phones.
37
+ """
38
+ indices = []
39
+
40
+ for index, phone in enumerate(phones):
41
+ if phone[0] in CONSONANTS and index < len(phones) - 1:
42
+ indices.append(index)
43
+
44
+ return indices
45
+
46
+
47
+ def _get_rhyming_tail(phones):
48
+ """
49
+ In preparation to search for multisyllabic rhymes, remove characters before the first vowel in phones.
50
+
51
+ For example, phones changes from ['G', 'IH0', 'T', 'AA1', 'R'] to ['IH0', 'T', 'AA1', 'R']
52
+ """
53
+ index = _get_vowel_index(phones)
54
+ return phones[index:]
55
+
56
+
57
+ def _slant_rhyme_consonants(phones):
58
+ """
59
+ Replaces intermediate consonants with a period, the wildcard character. The final consonant is preserved.
60
+
61
+ For example, replace the intermediate 'T' in ['IH0', 'T', 'AA1', 'R'], leaving ['IH0', '.', 'AA1', 'R']
62
+ """
63
+ consonant_indices = _get_consonant_indices(phones)
64
+ new_phones = copy.copy(phones)
65
+
66
+ for index in consonant_indices:
67
+ new_phones[index] = '.'
68
+
69
+ return new_phones
70
+
71
+
72
+ def get_perfect_rhymes(phones):
73
+ """
74
+ Given phones, search for perfect, multisyllabic rhymes with no syllables afterwards.
75
+ """
76
+ rhyming_tail = " ".join(_get_rhyming_tail(phones))
77
+ return pronouncing.search(rhyming_tail + "$")
78
+
79
+
80
+ def get_internal_rhymes(phones):
81
+ """
82
+ Given phones, search for internal, multisyllabic rhymes.
83
+ """
84
+ rhyming_tail = " ".join(_get_rhyming_tail(phones))
85
+ return pronouncing.search(rhyming_tail)
86
+
87
+
88
+ def get_slant_rhymes(phones):
89
+ """
90
+ Given phones, return all slant and internal rhymes.
91
+
92
+ Slant rhymes do not require matching consonants before the final position. For example, guitar and cigar.
93
+ Internal rhymes do not require the matching syllables to be final. For example, guitar and departure.
94
+ """
95
+ tail = _get_rhyming_tail(phones)
96
+ search = ' '.join(_slant_rhyme_consonants(tail))
97
+ return pronouncing.search(search)
98
+
99
+
100
+ def main(word):
101
+ """
102
+ Search for slant rhymes given word, an argument from the command line.
103
+
104
+ For an inputted word not recognized in the CMU dictionary, prompt user to try another word.
105
+ """
106
+ phones = get_phones(word)
107
+
108
+ if phones is None:
109
+ print('That word is not recognized. Please check the spelling and avoid proper nouns.')
110
+ exit(1)
111
+
112
+ perfect_rhymes = get_perfect_rhymes(phones)
113
+ internal_rhymes = get_internal_rhymes(phones)
114
+ slant_rhymes = get_slant_rhymes(phones)
115
+
116
+ perfects_without_word = set(perfect_rhymes) - {word}
117
+ internals_without_perfects = set(internal_rhymes) - set(perfect_rhymes) - {word}
118
+ imperfect_slants = set(slant_rhymes) - set(internal_rhymes) - {word}
119
+
120
+ if perfects_without_word:
121
+ print('Perfect rhymes:', ", ".join(sorted(perfects_without_word)), '\n')
122
+ else:
123
+ print('No perfect rhymes.\n')
124
+
125
+ if internals_without_perfects:
126
+ print('Internal rhymes:', ", ".join(sorted(internals_without_perfects)), '\n')
127
+ else:
128
+ print('No internal rhymes.\n')
129
+
130
+ if imperfect_slants:
131
+ print('Slant rhymes:', ", ".join(sorted(imperfect_slants)))
132
+ else:
133
+ print('No slant rhymes.')
134
+
135
+
136
+ if __name__ == '__main__':
137
+ if len(sys.argv) < 2:
138
+ print('Usage: multisyllabic_rhymer.py word, where word is the rhyme target.')
139
+ exit(1)
140
+
141
+ main(sys.argv[1])