From e045b8cade477a8002a4377c9b84bb9f05ef8eed Mon Sep 17 00:00:00 2001 From: Owen Jow Date: Thu, 29 Oct 2015 01:32:17 -0700 Subject: [PATCH] Upgraded my rhyme lookup algorithm --- css/style.css | 50 +++++++++++++------------- js/rhyme_lookup.js | 87 ++++++++++++++++++++++++++++++++++++---------- js/trie.js | 39 +++++++++++++++++++++ 3 files changed, 132 insertions(+), 44 deletions(-) diff --git a/css/style.css b/css/style.css index dd125ff..9bffe05 100644 --- a/css/style.css +++ b/css/style.css @@ -67,9 +67,9 @@ button { color: black; font-family: 'Roboto Condensed'; font-size: 42px; - font-weight: normal; - width: 120px; - height: 70px; + font-weight: normal; + width: 120px; + height: 70px; line-height: 60px; margin: auto; text-align: center; @@ -82,13 +82,13 @@ button { } button:hover { - background: #ead06c; + background: #ead06c; color: black; font-family: 'Roboto Condensed'; font-size: 42px; - font-weight: normal; - width: 120px; - height: 70px; + font-weight: normal; + width: 120px; + height: 70px; line-height: 60px; margin: auto; text-align: center; @@ -101,19 +101,19 @@ button:active { color: #ead06c; font-family: 'Roboto Condensed'; font-size: 42px; - font-weight: normal; - background: black; - border: 5px solid #ead06c; - width: 120px; - height: 70px; - transition: all 0.05s ease 0.1s; - opacity: 0.8; + font-weight: normal; + background: black; + border: 5px solid #ead06c; + width: 120px; + height: 70px; + transition: all 0.05s ease 0.1s; + opacity: 0.8; } div p { - font-family: 'Roboto Condensed'; - color: #ead06c; - font-size: 36px; + font-family: 'Roboto Condensed'; + color: #ead06c; + font-size: 36px; } .typed-cursor { @@ -167,12 +167,12 @@ div p { } #start { - height: 50px; - border-radius: 1px; - border: 0px solid #ead06c; - width: 120px; - height: 70px; - margin: auto; - margin-top: 130px; - text-align: center; + height: 50px; + border-radius: 1px; + border: 0px solid #ead06c; + width: 120px; + height: 70px; + margin: auto; + margin-top: 130px; + text-align: center; } diff --git a/js/rhyme_lookup.js b/js/rhyme_lookup.js index fe15172..9b33eaf 100644 --- a/js/rhyme_lookup.js +++ b/js/rhyme_lookup.js @@ -1,12 +1,6 @@ -// A function that transforms words into their associated IPA format -// i.e. mapping is English word --> IPA -var getIPAForm = function(word) { - /* Insert clever stuff here */ -}; - var mobytrie = new Trie(); -// Populate the mobypron trie +// Populate the mobypron trie [with pronunciations] for (var mobyword in mobypron) { if (mobypron.hasOwnProperty(mobyword)) { var fields = mobypron[mobyword].split(/\/+/); @@ -14,21 +8,76 @@ for (var mobyword in mobypron) { } } +// Populate a second trie with the words themselves +var wordTrie = new Trie(); + +var words = Object.keys(mobypron); +var numWords = words.length; + +for (var i = 0; i < numWords; i++) { + var word = words[i]; + wordTrie.insert(word.split(''), word); +} + +/* + * Returns a set of words from the mobypron trie that (hopefully) + * rhyme with the word specified by PRON_FIELDS. + */ +var fromTrie = function(pronFields) { + if (pronFields.length > 4) { + pronFields.splice(0, pronFields.length - 3); + } else if (pronFields.length > 2) { + pronFields.splice(0, pronFields.length - 2); + } + + var results = mobytrie.autoComplete(pronFields); + if (results.length == 0) { + return ["grandfather clock"]; // hey, we've got to return something! + } + + // Return a random word from results + return [results[Math.floor(Math.random() * results.length)]]; +} + +/* + * Like fromTrie, except an "s" will automatically be appended to the resulting rhyme. + */ +var pluralFromTrie = function(pronFields) { + var rhyme = fromTrie(pronFields); + rhyme[0] = rhyme[0].concat("s"); + return rhyme; +} + var lookup = function(word) { - if (mobypron.hasOwnProperty(word)) { - var pronFields = mobypron[word].split(/\/+/); - if (pronFields.length > 4) { - pronFields.splice(0, pronFields.length - 3); - } else if (pronFields.length > 2) { - pronFields.splice(0, pronFields.length - 2); + if (word.slice(-1) === "*") { + switch (word) { + case "n****": + return ["gold digga"]; + case "f***": + return ["luck"]; + case "s***": + return ["hit"]; + } + } else if (mobypron.hasOwnProperty(word)) { + return fromTrie(mobypron[word].split(/\/+/)); + } else if (mobypron.hasOwnProperty(word.toLowerCase())) { + return fromTrie(mobypron[word.toLowerCase()].split(/\/+/)); + } else { + var singular = word.substring(0, word.length - 1); + if (word.slice(-1) === "s" && mobypron.hasOwnProperty(singular)) { + return pluralFromTrie(mobypron[singular].split(/\/+/)); } - var results = mobytrie.autoComplete(pronFields); - if (results.length == 0) { return []; } + var approximation = wordTrie.getApproximation(word.toLowerCase().split('')); + if (approximation == null && word.slice(-1) === "s") { // plurality case + approximation = wordTrie.getApproximation(singular.split('')); + if (approximation == null) { + return ["grandmother clock"]; + } else { + return pluralFromTrie(mobypron[approximation].split(/\/+/)); + } + } - // Return a random word from results - return [results[Math.floor(Math.random() * results.length)]]; - } else { - return []; + return fromTrie(mobypron[approximation].split(/\/+/)); } }; diff --git a/js/trie.js b/js/trie.js index 1ccac53..b99226a 100644 --- a/js/trie.js +++ b/js/trie.js @@ -57,6 +57,25 @@ Trie.prototype = { return words; }, + /* + * Gets a single word from the trie (the first one it finds). + */ + getOneWord: function() { + if (this.word != null) { + return this.word; + } else { + var word = null; + for (c in this.children) { + word = this.children[c].getOneWord(); + if (word != null) { + break; + } + } + + return word; + } + }, + /* * Autocompletes the given suffix. * @@ -77,5 +96,25 @@ Trie.prototype = { fields.pop(); return child.autoComplete(fields); } + }, + + /* + * Returns an approximation of the given word. + * It is assumed that the word does not already exist in the trie; + * thus, this function works by following the characters of the word + * (starting from the end) through the trie – and when it reaches a dead end, + * it returns an approximation from th set of all of the dead end node's children. + * + * @param {Array} charArray An array of characters to follow + * @return {String} An approximation of the word specified by CHAR_ARRAY + */ + getApproximation: function(charArray) { + child = this.children[charArray[charArray.length - 1]]; + if (child === undefined) { + return this.getOneWord(); + } else { + charArray.pop(); + return child.getApproximation(charArray); + } } };