patternpythonMinor
A Very Poetic Program
Viewed 0 times
programpoeticvery
Problem
This program is basically a rhyming dictionary. It makes use of Sphinx's groups phonemic dictionary of English which includes a lot of words broken into their respective phonemes, and if we assume that, at least for most cases, anytime the two last phonemes match, the two words rhyme, then it's very easy to whip up a program that does so. Here's my try at this:
Of course it's naive to assume that EVERYTIME the last two phonemes of two different words match, they rhyme, but most of the times, they do.
This program returns a list of matching words broken into their respective phonemes.
I spent two years studying English literature before I dropped out in favor of pursuing computer programming so I'm qualified to say that I barely know what a phoneme is.
import requests
import os
import re
def load_library():
with open('library.txt', 'r') as library:
lines = library.readlines()
return [x for x in lines if not x.startswith(';;;')]
def rhyme(string):
if os.path.isfile('library.txt'):
library = load_library()
else:
url = "http://svn.code.sf.net/p/cmusphinx/code/trunk/cmudict/cmudict-0.7b"
response = requests.get(url, stream=True)
if not response.ok:
print("Error loading library")
with open('library.txt', 'wb+') as library:
for block in response.iter_content(32):
library.write(block)
library = load_library()
string = string.upper()
phonemes = [y for y in library if y.startswith(string)][0][len(string):]
phonemes_split = str.strip(phonemes).split(' ')
matches = [z for z in library if z.endswith(phonemes_split[-2] + ' ' + phonemes_split[-1] + '\n')]
matches = [z.strip().split(' ') for z in matches]
return matchesOf course it's naive to assume that EVERYTIME the last two phonemes of two different words match, they rhyme, but most of the times, they do.
This program returns a list of matching words broken into their respective phonemes.
I spent two years studying English literature before I dropped out in favor of pursuing computer programming so I'm qualified to say that I barely know what a phoneme is.
Solution
Library loaded twice
If
I guess this was just an oversight, with a simple fix:
Filter while loading
Instead of loading the library first and then filtering out the commented lines, it would be better to filter as you read:
Use generator expressions for better performance
It's a pity to loop over the entire list and filtering when you will only use the first match:
You would do better with a generator expression,
which is more or less as simple as replacing the surrounding
However, generators are not subscriptable, so to get the first element you must use the
If
library.txt exists, it will get loaded twice:if os.path.isfile('library.txt'):
library = load_library()
else:
# download the file ...
library = load_library()I guess this was just an oversight, with a simple fix:
if not os.path.isfile('library.txt'):
# download the file ...
library = load_library()Filter while loading
Instead of loading the library first and then filtering out the commented lines, it would be better to filter as you read:
with open('library.txt', 'r') as library:
return [line for line in library if not line.startswith(';;;')]Use generator expressions for better performance
It's a pity to loop over the entire list and filtering when you will only use the first match:
phonemes = [y for y in library if y.startswith(string)][0][len(string):]You would do better with a generator expression,
which is more or less as simple as replacing the surrounding
[...] with (...).However, generators are not subscriptable, so to get the first element you must use the
next(...) builtin:phonemes = next(y for y in library if y.startswith(string))[len(string):]Code Snippets
if os.path.isfile('library.txt'):
library = load_library()
else:
# download the file ...
library = load_library()if not os.path.isfile('library.txt'):
# download the file ...
library = load_library()with open('library.txt', 'r') as library:
return [line for line in library if not line.startswith(';;;')]phonemes = [y for y in library if y.startswith(string)][0][len(string):]phonemes = next(y for y in library if y.startswith(string))[len(string):]Context
StackExchange Code Review Q#140029, answer score: 5
Revisions (0)
No revisions yet.