def smooth_join(x, y): ''' joins while alternating vowels and consonants to make strings roll off the tongue. prioritize first string. ''' if len(x) == 0 or len(y) == 0: return None if is_consonant(x[-1]): if is_consonant(y[0]): y = y[1:] return x + y return x + y
def portmanteau(x, y, verbose=False): x = x.lower() y = y.lower() solutions = set() # Join on longest common substring substrs = list(lcs(x, y)) # Remove standalone vowels substrs = [s for s in substrs if is_consonant(s)] for substr in substrs: solutions.update(join_on_substr(x, y, substr)) # Try joining near ends solutions.add(join_near(x, y)) solutions.add(join_near(x, y, join_on_vowel=False)) solutions.add(join_near(y, x)) solutions.add(join_near(y, x, join_on_vowel=False)) # Try joining on syllables solutions.update(syllable_join(x, y)) # Clean & print best solutions.discard(None) solutions.discard('') if verbose: for s in solutions: print s, score(x,y,s, verbose=verbose) return (max(solutions, key=lambda s: score(x,y,s, verbose=verbose)) if solutions else None)
def portmanteau(x, y, verbose=False): x = x.lower() y = y.lower() solutions = set() # Join on longest common substring substrs = list(lcs(x, y)) # Remove standalone vowels substrs = [s for s in substrs if is_consonant(s)] for substr in substrs: solutions.update(join_on_substr(x, y, substr)) # Try joining near ends solutions.add(join_near(x, y)) solutions.add(join_near(x, y, join_on_vowel=False)) solutions.add(join_near(y, x)) solutions.add(join_near(y, x, join_on_vowel=False)) # Try joining on syllables solutions.update(syllable_join(x, y)) # Clean & print best solutions.discard(None) solutions.discard('') if verbose: for s in solutions: print s, score(x, y, s, verbose=verbose) return (max(solutions, key=lambda s: score(x, y, s, verbose=verbose)) if solutions else None)
def join_on_substr(x, y, substr): ''' Return all solutions of two strings joined on common substring. Works for multiple occurrences of `substr`. ''' sslen = len(substr) solutions = set() # todo minimize dist for i in indices(x, substr): for j in indices(y, substr): # if substring is only one consonant from the end, incorporate it if i+sslen == len(x) - 1 and is_consonant(x[-1]): solutions.add(smooth_join(x[:i] + substr + x[-1], y[j+sslen:])) else: solutions.add(smooth_join(x[:i] + substr, y[j+sslen:])) if j+sslen == len(y) - 1 and is_consonant(y[-1]): solutions.add(smooth_join(y[:j] + substr + y[-1], x[i+sslen:])) else: solutions.add(smooth_join(y[:j] + substr, x[i+sslen:])) return solutions
def syllable_join(x, y): ''' Return solutions for joining on syllables. ''' solutions = set() x_syllables = get_syllables(x) y_syllables = get_syllables(y) if not x_syllables or not y_syllables: return solutions for i, x_syl in enumerate(x_syllables): for j, y_syl in enumerate(y_syllables): # Add if stresses alternate at the join point. if is_stressed(x_syl) != is_stressed(y_syl): #if not is_stressed(x_syl) and is_stressed(y_syl): # Also make sure we don't have consecutive vowels. Consonants ok. if is_consonant(x_syl['text'][-1]) or is_consonant(y_syl['text'][0]): solutions.add(concat_syllables(x_syllables[:i+1] + y_syllables[j:])) return solutions
def join_on_substr(x, y, substr): ''' Return all solutions of two strings joined on common substring. Works for multiple occurrences of `substr`. ''' sslen = len(substr) solutions = set() # todo minimize dist for i in indices(x, substr): for j in indices(y, substr): # if substring is only one consonant from the end, incorporate it if i + sslen == len(x) - 1 and is_consonant(x[-1]): solutions.add( smooth_join(x[:i] + substr + x[-1], y[j + sslen:])) else: solutions.add(smooth_join(x[:i] + substr, y[j + sslen:])) if j + sslen == len(y) - 1 and is_consonant(y[-1]): solutions.add( smooth_join(y[:j] + substr + y[-1], x[i + sslen:])) else: solutions.add(smooth_join(y[:j] + substr, x[i + sslen:])) return solutions
def syllable_join(x, y): ''' Return solutions for joining on syllables. ''' solutions = set() x_syllables = get_syllables(x) y_syllables = get_syllables(y) if not x_syllables or not y_syllables: return solutions for i, x_syl in enumerate(x_syllables): for j, y_syl in enumerate(y_syllables): # Add if stresses alternate at the join point. if is_stressed(x_syl) != is_stressed(y_syl): #if not is_stressed(x_syl) and is_stressed(y_syl): # Also make sure we don't have consecutive vowels. Consonants ok. if is_consonant(x_syl['text'][-1]) or is_consonant( y_syl['text'][0]): solutions.add( concat_syllables(x_syllables[:i + 1] + y_syllables[j:])) return solutions