Skip to content

Instantly share code, notes, and snippets.

@DeCarabas
Created May 6, 2020 21:13
Show Gist options
  • Save DeCarabas/7f2a66e4272b87fbf95f6e7914659edb to your computer and use it in GitHub Desktop.
Save DeCarabas/7f2a66e4272b87fbf95f6e7914659edb to your computer and use it in GitHub Desktop.
let fs = require('fs')
const cmu_dict: string = fs.readFileSync('cmudict-0.7b', 'utf-8')
type Rhyme = string[]
type WordToRhyme = {
[word: string]: Rhyme
};
const word_to_rhyme =
cmu_dict.split('\n')
.filter(line => !line.startsWith(';'))
.map(line => line.split(/\s+/))
.reduce((m: WordToRhyme, [word, ...phonemes]): WordToRhyme => {
m[word] = phonemes.reverse();
return m;
}, {})
type TrieNode = {
[syllable: string]: string|TrieNode|undefined,
terminate?: string
};
const rhyme_to_words: TrieNode = (function() {
let result: TrieNode = {};
for (let [k, v] of Object.entries(word_to_rhyme)) {
let cursor = result;
for (let syllable of v) {
const next = cursor[syllable];
if (typeof next === 'string') {
throw Error('Unexpected syllable: ' + syllable);
} else if (next === undefined) {
cursor = cursor[syllable] = {}
} else {
cursor = next;
}
}
cursor['terminate'] = k;
}
return result;
})();
function findAllWords(m: TrieNode): string[] {
let results = [];
let stack = [m];
for (;;) {
let top = stack.pop();
if (!top) {
break;
}
for (let [k, v] of Object.entries(top)) {
if (typeof v === 'string') {
results.push(v);
} else {
stack.push(v ?? {});
}
}
}
return results;
}
function findRhymes(word: string): string[] {
let rhyme = (word_to_rhyme[word.toUpperCase()] || []).slice(0, 3)
let cursor: TrieNode = rhyme_to_words
for (let syllable of rhyme) {
const next = cursor[syllable];
if (next === undefined || typeof next === 'string') {
cursor = {};
} else {
cursor = next;
}
}
return findAllWords(cursor)
}
console.log(findRhymes('adamant'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment