def line_rhymescheme(self, line): """ Creates rhyme scheme for a given line. :param line: line of lyrics, str :return: last two morphemes of the last word in line, str """ end_word = re.sub(r"\W+", '', get_last_word(line)).lower() pronunciation_list = pronouncing.phones_for_word(end_word) if pronunciation_list: potential_rhymes = {} sound_pairs = [] for item in pronunciation_list: sound_pair = item.split(' ')[-2:] if len(sound_pair) < 2: for sound1 in self.sound_dict[sound_pair[0]]: sound_pairs.append((sound1, '')) else: for sound1 in self.sound_dict[sound_pair[0]]: for sound2 in self.sound_dict[sound_pair[1]]: sound_pairs.append((sound1, sound2)) for sound_pair in sound_pairs: if sound_pair not in potential_rhymes.keys(): potential_rhymes[sound_pair] = 0 if sound_pair[1] == '': potential_rhymes[sound_pair] += len(pronouncing.search(sound_pair[0] + "$")) else: potential_rhymes[sound_pair] += len(pronouncing.search(sound_pair[0] + " " + sound_pair[1] + "$")) most_freq_pair = max(potential_rhymes.items(), key=operator.itemgetter(1))[0] rhymescheme = most_freq_pair[0] + ' ' + most_freq_pair[1] else: rhymescheme = end_word[-2:] return rhymescheme
def search_match_by_regex(): phones_sigh = pronouncing.phones_for_word("jest")[0] print phones_sigh print pronouncing.search(phones_sigh)[:5] #finds all of the words that end in -iddle phone_iddle = pronouncing.search("IH1 D AH0 L$") print phone_iddle
def test_search(self): matches = pronouncing.search('^S K L') self.assertEqual(matches, ['sclafani', 'scleroderma', 'sclerosis', 'sklar', 'sklenar']) matches = pronouncing.search('IH. \w* IH. \w* IH. \w* IH.') self.assertEqual(matches, ['definitive', 'definitively', 'diminishes', 'diminishing', 'elicited', 'miscibility', 'primitivistic', 'privileges'])
def test_search(self): matches = pronouncing.search('^S K L') self.assertEqual( matches, ['sclafani', 'scleroderma', 'sclerosis', 'sklar', 'sklenar']) matches = pronouncing.search('IH. \w* IH. \w* IH. \w* IH.') self.assertEqual(matches, [ 'definitive', 'definitively', 'diminishes', 'diminishing', 'elicited', 'miscibility', 'primitivistic', 'privileges' ])
def plus_one_matcher(self): """ PlusOneMatcher(letters: list of Letter) Finds matches for the exact phone plus one letter in the beginning or in the end """ matches = [] matches += pronouncing.search('^(\\S+ )%s$' % self.word.phone) matches += pronouncing.search('^%s( \\S+)$' % self.word.phone) return self._filter_matches(matches) if matches else None
def random_match_phones(word, phones=None): """Returns words that match a random combination of phonemes This is like a random general rhyme, however instead of just the last syllable portion, it's the entire word. :param word: word that should be in the CMU Pronouncing Dictionary :param phones: specific phonemes to rhyme with (default None) :return: a word that shares a random combinations of phonemes """ if phones is None: phones = first_phones_for_word(word) if phones == "": return [] else: if phones not in pronouncing.phones_for_word(word): raise ValueError("phonemes and word don't match") if not phones: raise ValueError("phonemes string is empty") search_list = wildcard_mix_phones_regex_searches(phones) while search_list: search = random.choice(search_list) rhymes = pronouncing.search(search) if rhymes: rhymes = unique(rhymes) if word in rhymes: rhymes.remove(word) return rhymes else: search_list.remove(search) print( "random general match phones: tried all combos, didn't find anything!") return []
def render(self): if self.cf['hose']: self.hose = re.compile(self.cf['hose']) else: self.hose = None participles = self.syllfilt(pronouncing.search("IH0 NG$"), 2) nouns = self.syllfilt(pronouncing.rhymes('now'), 1) rhymes = [] p1 = None p3 = None while not rhymes: ps = random.sample(participles, 2) rhymes = self.syllfilt(pronouncing.rhymes(ps[0]), 2) p1 = ps[0] p2 = random.choice(rhymes) p3 = ps[1] noun = random.choice(nouns) if noun[0] in 'aeoiu': noun = ' an ' + noun else: noun = ' a ' + noun text = "You can get it " + p1 + "\n" text += "You can get it " + p2 + "\n" text += "You can get it " + p3 + noun + "\n" text += "Matter of fact I've got it now" return text
def random_general_rhyme(word, phones=None, search_option="end"): """ Return a list of rhymes where a random combination of phonemes match The conditions for a general rhyme between words are: (1) Any possible phonetic similarity between the final stressed vowel and subsequent phonemes. If phones argument not given, phones/pronunciation used will default to the first in the list of phones returned for word. If no rhyme is found, an empty list is returned. :param word: a word :param phones: specific CMUdict phonemes string for word (default None) :param search_option option for regex search. (default "end") :return: a list of rhymes for word, where specific rhyme is random """ if phones is None: phones = first_phones_for_word(word) if phones == "": return [] else: if phones not in pronouncing.phones_for_word(word): raise ValueError(phones + " not phones for +" + word) if not phones: raise ValueError("phonemes string is empty") rp = pronouncing.rhyming_part(phones) search_combos = wildcard_mix_phones_regex_searches(rp) while search_combos: search = random.choice(search_combos) if search_option == "end": rhymes = pronouncing.search(search + "$") elif search_option == "begin": rhymes = pronouncing.search("^" + search) elif search_option == "whole": rhymes = pronouncing.search("^" + search + "$") else: raise ValueError( "search_option should be 'end', 'begin', or 'whole'") if rhymes: rhymes = unique(rhymes) if word in rhymes: rhymes.remove(word) return rhymes else: search_combos.remove(search) print("random general rhyme: tried all combos, didn't find anything!") return []
def get_rhymes(word): pronunciations = pronouncing.phones_for_word(word) rhymes = set() for pronunciation in pronunciations: rhyming_part = pronouncing.rhyming_part(pronunciation) curr_rhymes = pronouncing.search(rhyming_part + "$") rhymes.update(curr_rhymes) return rhymes
def get_alliterations(word, phone_count=2): pronunciations = pronouncing.phones_for_word(word) alliterations = set() for pronunciation in pronunciations: first_phones = pronunciation.split()[:phone_count] curr_alliterations = pronouncing.search('^' + ' '.join(first_phones)) alliterations.update(curr_alliterations) return alliterations
def exact_matcher(self): """ ExactMatcher(letters: list of Letter): 0 Finds only exact matches for the phone of the word """ matches = pronouncing.search('^%s$' % self.word.phone) return self._filter_matches(matches) if matches else None
def test_search(self): matches = pronouncing.search("^S K L") self.assertEqual(matches, ["sclafani", "scleroderma", "sclerosis", "sklar", "sklenar"]) matches = pronouncing.search("IH. \w* IH. \w* IH. \w* IH.") self.assertEqual( matches, [ "definitive", "definitively", "diminishes", "diminishing", "elicited", "miscibility", "primitivistic", "privileges", ], )
def replace_rand(): # re-writes a text by taking each word and replacing it with a random word that begin with the same first two phone out = list() for word in text.split(): phones = pronouncing.phones_for_word(word)[0] first2 = phones.split()[:2] out.append(random.choice(pronouncing.search("^" + " ".join(first2)))) print ' '.join(out)
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 get_rhyme(word): phones = pronouncing.phones_for_word(word) phone_parts = pronouncing.rhyming_part(phones[0]) rhymes = pronouncing.search(phone_parts + "$") # ensures rhyming word is not the same as given word rhyme = word.lower() while rhyme == word.lower(): rhyme = random.choice(rhymes) return rhyme
def word_search(syllable_list): regex = '^\D*' + '\D*'.join(syllable_list) + '\D*$' pat_len = len(syllable_list) results = [] while(not results): #print "WORD SEARCH IS ABOUT TO LOOK FOR THIS PATTERN: " #print regex #print "IT'S %d SYLLABLES LONG." % pat_len results = pronouncing.search(regex) pat_len -= 1 regex = '^\D*' + '\D*'.join(syllable_list[:pat_len]) + '\D*$' return results, pat_len + 1
def steal_voices(): words_ending_with_sounds = pr.search("S IH0 [ZS]$") words_with_stresses = pr.search_stresses("[12][12]0") words_with_sounds_and_stresses = set( words_ending_with_sounds).intersection(words_with_stresses) # Find words with correct syllable count three_syllable_words = [] for word in words_with_sounds_and_stresses: word_phones = pr.phones_for_word(word) syllable_count = pr.syllable_count(word_phones[0]) if syllable_count == 3: three_syllable_words.append(word) return three_syllable_words
def get_fortune(word, fortunes, actions): phones = pronouncing.phones_for_word(word) phone_parts = pronouncing.rhyming_part(phones[0]) rhymes = pronouncing.search(phone_parts + "$") for fortune in fortunes: last_word = fortune.split(" ")[-1] if last_word in rhymes: return fortune, "fortune" for action in actions: last_word = action.split(" ")[-1] if last_word in rhymes: return action, "action" return "Sorry!", "error"
def consonance_slant_rhyme(word, phones=None): """ Returns slant rhymes defined by consonance i.e. matching consonants. The conditions for a consonance slant rhyme between words are: (1) The last stressed vowel and subsequent phonemes match all consonants. If phones argument not given, phones/pronunciation used will default to the first in the list of phones returned for word. If no rhyme is found, an empty list is returned. Slant rhymes seems to have various different meanings. I went ahead and set the condition of having to have ALL the same vowels and different consonants or vice versa. :param word: a word :param phones: specific CMUdict phonemes string for word (default None) :return: a list consonance slant rhymes for word """ if phones is None: phones = first_phones_for_word(word) if phones == "": return [] else: if phones not in pronouncing.phones_for_word(word): raise ValueError(phones + " not phones for +" + word) if not phones: raise ValueError("phonemes string is empty") phones_list = phones.split() search_list = [] for i in range(len(phones_list) - 1, -1, -1): phone = phones_list[i] if check_if_stressed_vowel(phone): search_list.append('.{1,3}') if all_the_same(search_list, '.{1,3}') is True: break search_list.reverse() search = ' '.join(search_list) rhymes = pronouncing.search(search + "$") rhymes = unique(rhymes) if word in rhymes: rhymes.remove(word) return rhymes elif check_if_non_stressed_vowel(phone): search_list.append('.{1,3}') elif check_if_consonant(phone): search_list.append(phone) return []
def _similiar_pronounciation(word: str) -> List[str]: """Find possible mates using pronunciation search.""" mates: List[str] = [] first_phones = pronouncing.phones_for_word(word)[0] phones = first_phones.split(" ") i = 0 while not mates and i < len(phones): # TODO: Generalize consonant sounds search_pattern = f"^{' '.join(phones[i:])}" matches = pronouncing.search(search_pattern) distinct_matches = [match for match in matches if match.find(word) < 0] if len(distinct_matches) > 0: mates = distinct_matches else: i += 1 return mates
def consonance(word, phones=None, search_direction=None, match_limit=None): """Returns words that have consonance :param word: word that should be in the CMU Pronouncing Dictionary :param phones: specific phonemes to rhyme with (default None) :param match_limit: limit number of words to return :return: a word that has repition of consonance sounds to input word """ if phones is None: phones = first_phones_for_word(word) if phones == "": return [] else: if phones not in pronouncing.phones_for_word(word): raise ValueError("phonemes and word don't match") if not phones: raise ValueError("phonemes string is empty") phones_list = phones.split() if search_direction == "backward": phones_list.reverse() search_list = [] match_cnt = 0 for phone in phones_list: if check_if_vowel(phone): search_list.append('.{1,3}') elif check_if_consonant(phone): search_list.append(phone) match_cnt += 1 if (match_limit is not None) and (match_cnt == match_limit): break if search_direction == "backward": search = ' '.join(search_list.reverse()) + "$" elif search_direction == "forward": search = "^" + ' '.join(search_list) else: search = ' '.join(search_list) rhymes = pronouncing.search(search) rhymes = unique(rhymes) if word in rhymes: rhymes.remove(word) return rhymes
def find_words(): # Find words with mattching stress patterns beluga_phones = pr.phones_for_word("beluga") last_beluga_phone = pr.phones_for_word("beluga")[0].split(" ")[-1] beluga_stresses = pr.stresses(beluga_phones[0]) words_with_stress_pattern = pr.search_stresses(beluga_stresses) # Find words with matching end phone words_ending_with_ah = pr.search(last_beluga_phone + "$") # Find words with correct syllable count words_with_stress_and_ending = list( set(words_with_stress_pattern).intersection(words_ending_with_ah)) three_syllable_words = [] for word in words_with_stress_and_ending: word_phones = pr.phones_for_word(word) syllable_count = pr.syllable_count(word_phones[0]) if syllable_count == 3: three_syllable_words.append(word) return three_syllable_words
def near_rhyme(word, phones=None, stress=True, consonant_tail=0): """ Returns a list of words that almost rhyme The conditions for a near rhyme between words are: (1) At least one of the phonemes after and including the last stressed syllable match, except for the case where they all do. If phones argument not given, phones/pronunciation used will default to the first in the list of phones returned for word. If no rhyme is found, an empty list is returned. :param word: a word :param phones: specific CMUdict phonemes string for word (default None) :param stress: if vowels will match stress (default True) :param consannt_tail: number of :return: a list of near rhymes for word """ if phones is None: phones = first_phones_for_word(word) if phones == "": return [] else: if phones not in pronouncing.phones_for_word(word): raise ValueError(phones + " not phones for" + word) if not phones: raise ValueError("phonemes string is empty") rp = pronouncing.rhyming_part(phones) search_combos = wildcard_mix_phones_regex_searches(rp, stress) rhymes = [] for search in search_combos: rhymes += pronouncing.search(search + "( .{1,3}){0," + str(consonant_tail) + "}$") if rhymes: rhymes = unique(rhymes) if word in rhymes: rhymes.remove(word) return rhymes print("random general rhyme: tried all combos, didn't find anything!") return []
def main(args): Word = namedtuple("Word", "prefix word") WORDS = [ Word("na", "national"), Word("no", "novel"), Word("gen", "generation"), Word("mo", "month"), ] word_store = defaultdict() for word in WORDS: phones = pronouncing.phones_for_word(word.word) part = initial_rhyming_part(phones[0]) words = pronouncing.search(f"^{part}") # Keep those that start with the prefix # eg. ditch "gnatcatcher" for national's "na" # Also don't include "national", "novel", "generation", "month" or "nazism" words = { w for w in words if w.startswith(word.prefix) and not w.startswith(word.word) } word_store[word.word] = list(words - {"nazism"}) # print(len(words)) # Generate something total = 0 while total < args.words: things = [ random.choice(word_store[word.word]).capitalize() for word in WORDS ] total += len(things) # print(" ".join(things)) # ASCII code 11 (0x0B), soft newline in Word, good for Justify Text # print(" ".join(things), end="\x0b") print("\t".join(things)) print(f"{total} words")
def sim_word_for_phones(phones, word_list=[], sim_perc=0.25): """Finds a word that has shared phonemes to input phonemes :param phones: CMU Pronouncing Dictionary phonemes string :param word_list: list of words to limit search to :sim_perc: threshold for similarity between phones and words in words_list :return: word that has number of phonemes the same as phones """ search_combos = wildcard_mix_phones_regex_searches(phones) random.shuffle(search_combos) for sch in search_combos: sch_list = sch.split(" ") if sch_list.count(".{1,3}") < (1 - sim_perc) * len(sch_list): matches = pronouncing.search("^" + sch + "$") if matches: matches = unique(matches) random.shuffle(matches) for m in matches: if word_list: if m in word_list: return (m) else: return (m) return None
verse += word + " " verse += "\n" verse += "\n" verse = verse.rstrip() print("~*~ ~*~ ~*~ verse ~*~ ~*~ ~*~") print(verse) print("~*~ ~*~ ~*~ ~*~ ~*~ ~*~ ~*~ ~*~") #===================================================== print("\nokay, now make it rhyme a bit?\n") print(" SURE.\n") introduction = "" chorus = [] bridge = "" end = "" # random_verse() cmu_word_list = pronouncing.search(".") list_intersect = list(set(cmu_word_list).intersection(google_word_list)) verse_schemes = [] subscheme_num = int(max(1, random.gauss(3, 1))) for sn in range(0, subscheme_num): scheme = rand_rhyme_scheme() scheme_traits = define_scheme_traits(list_intersect) line_num = len(scheme) repeat_num = random.choice([1, 3]) for rn in range(0, repeat_num): scheme_lines = [] for ln in range(0, line_num): letter = scheme[ln] sylb_num = scheme_traits[letter]['syl'] rhyme_word = scheme_traits[letter]['rhym'] timeout_cnt = 0
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_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 + "$")
import pronouncing, random FIRSTWORD = 'alexander' SECONDWORD = 'hamilton' def nsyl(word): pronunciation_list = pronouncing.phones_for_word(word) return pronouncing.syllable_count(pronunciation_list[0]) firstnum = nsyl(FIRSTWORD) secondnum = nsyl(SECONDWORD) firstwords = [] secondwords = [] first_stresses = set(pronouncing.stresses_for_word(FIRSTWORD)) second_stresses = set(pronouncing.stresses_for_word(SECONDWORD)) for word in pronouncing.search('.*'): if "'" in word: continue cnt = nsyl(word) if cnt in (firstnum, secondnum): stresses = set(pronouncing.stresses_for_word(word)) if cnt == firstnum and stresses & first_stresses: firstwords.append(word) if cnt == secondnum and stresses & second_stresses: secondwords.append(word) for i in range(50): print random.choice(firstwords), random.choice(secondwords)
import syllables as syl import pronouncing import random import re pronouncing.init_cmu() valid_words = pronouncing.lookup.keys() valid_words.sort() # make lists of words that are 8 syllables or less, 7 syllables or less, 6 or less, etc down to 1 # store as variables so we don't have to run that regex over and over n_syllables_or_less = {} for i in range(1, 10): regex = "^[A-Z\s]*(([A-Z]{2}[0-9])[\sA-Z]*){,%d}$" % i n_syllables_or_less[i] = pronouncing.search(regex) def valid_rhymes(word, num_syllables=8): word_rhymes = pronouncing.rhymes(word) word_valid_rhymes = filter( lambda (w): w in n_syllables_or_less[num_syllables], word_rhymes) return word_valid_rhymes def choose_from_rhymes(rhymes): choice = random.choice(rhymes) rhymes.remove(choice) return choice def starting_words(num_rhymes=3, num_syllables=8):
# First thing to be determined is the length of the triangle N, which equals to the length of the first line # It has N lines, the last line contains only one word # The first word of each line starts from a phone of AA1 R (referencing art) import pronouncing as pr from textblob import TextBlob import sys import random ## PART ONE >> Generate a pool for the first word of each line #search for the pronouncing or the first two syllabus in the word art #print ar gives us result as "AA1 R" which has 5 characters ar = pr.phones_for_word('art')[0][:5] ar_wordlist = list() ar_wordlist = pr.search('^' + ar) ar_short = list() #select the word less then 9 characters into a new list ar_short for word in ar_wordlist: if len(word) < 9: ar_short.append(word) #recombine the words in the list together to a string to feed into textblob ar_short_text = " ".join(ar_short) blob = TextBlob(ar_short_text) tags = blob.tags #create a list to hold the nouns within the list ar_short ar_nouns = list() for word, tag in blob.tags: if 'NN' in tag:
def identical_rhyme(word, phones=None): """ Returns identical rhymes of word. The conditions for an identical rhyme between words are: (1) last stressed vowel and subsequent phonemes match (2) onset of last stressed syllable is the same e.g. 'leave' and 'leave', or 'leave' and 'believe' If phones argument not given, phones/pronunciation used will default to the first in the list of phones returned for word. If no rhyme is found, an empty list is returned. The identical part of the word doesn't have to be a 'real' word. e.g. The phonemes for 'vection' will be used to find identical rhymes of 'convection' (e.g. advection) even though 'vection' is unusual/obscure. :param word: a word :param phones: specific CMUdict phonemes string for word (default None) :return: a list of identical rhymes for word """ if phones is None: phones = first_phones_for_word(word) if phones == "": return [] else: if phones not in pronouncing.phones_for_word(word): raise ValueError(phones + " not phones for +" + word) if not phones: raise ValueError("phonemes string is empty") phones_list = phones.split() search_list = [] for i in range(len(phones_list) - 1, -1, -1): phone = phones_list[i] if check_if_stressed_vowel(phone) is False: search_list.append(phone) else: search_list.append(phone) last_stressed_vowel_at_start = (i == 0) if last_stressed_vowel_at_start is True: search_list.reverse() search = ' '.join(search_list) rhymes = pronouncing.search(search + "$") return rhymes else: consonant_cnt = 0 consonants = "" search_start = "" for j in range(i, 0, -1): next_phone = phones_list[j - 1] if check_if_consonant(next_phone) is True: consonant_cnt += 1 if consonant_cnt > 1: consonants = next_phone + " " + consonants if check_if_consonant_cluster(consonants): search_list.append(next_phone) else: break else: consonants = next_phone search_list.append(next_phone) else: if consonant_cnt == 0: # null onset # Regex: vowel (AA1, EH0, ect.) or start '^' # pretty sure all vowel start two letters... # (would be "((.{1,2}(0|1|2) )|^)" otherwise) search_start = "((..(0|1|2) )|^)" break search_list.reverse() search = search_start + ' '.join(search_list) + "$" rhymes = pronouncing.search(search) rhymes = unique(rhymes) # for r in rhymes: # print(pronouncing.phones_for_word(r)[0]) return rhymes
def simPro(word): phones = pronouncing.phones_for_word(word)[0] p = pronouncing.search(phones)[:5] print(p)