Javascript poem-generator-- matching a substring to any individual element in an array

Viewed 604

I had no idea how to write this question's title, because this is a many-step question!

Some background: I'm trying to combine my background in English literature and grammar, my love of the "lik the bred" meme-poems, and my burgeoning javascript knowledge to create a "lik the bred" poem generator.

Basically, the user inputs a single-syllable name/noun, and based on that word, the rhyming poem will spawn. The logic for that first bit goes as follows:

  • Step one: get user's input
  • Step two: figure out how long user's input is (this step might not actually be necessary)
  • Step three: find first vowel (only including "y" if it's the only vowel-- alternatively, only include "y" if it's the last letter)
  • Step four: select all of the letters including and after that vowel
  • Step five: compare those letters to possible end rhymes

The problem is, I'm not sure how to handle steps three and four. (I'm open to solutions using jQuery or javascript libraries, but since I'm still a beginner, I haven't branched out much into writing anything but straight javascript from scratch.

NB: If an upper limit for length is helpful, nine characters would make sense, since the longest one-syllable words in the English language are 9 letters long.

My first thought was to do a conditional statement, something like:

var noun = document.getElementById('noun').value; // noun input by user
var n = noun.str.length; // length of unknown word
var place = 0
var firstVow; // location of first vowel
while (place < 10) { 
// can you even do nested while loops/conditionals like this?
    if (noun.charAt(place) == 'a' ||
        noun.charAt(place) == 'e' ||
        noun.charAt(place) == 'i' ||
        noun.charAt(place) == 'o' ||
        noun.charAt(place) == 'u'|| 
        noun.charAt(n) == 'y') {
           firstVow = noun.indexOf(place);}
    else {
        place++;
    }
}
 var numSel = n - firstVow; // number of characters to select equals string length minus location of the first vowel
 var nounSel = noun.substr(firstVow, numSel); // selection to compare to end-rhymes

In theory (at least I think-- please correct me if I'm wrong), that gets me as far as finding the first time a/e/i/o/u/word-terminal-y shows up, and then pulls the substring to compare to the various end rhymes... but then I'm lost.

I'm in the process of compiling a list of possible end rhymes, but I'm not sure how to go about comparing them to the substring (there are going to be tons of them, especially the ones with different spellings). If I made a variable for each rhyme sound, with an array for different spellings, is there a way to check if a string matches any one element in an array? I'm trying to avoid having a conditional statement with a hundred or more conditions if at all possible.

Any assistance or critique would be most welcome!

Edit for examples:

Some examples of what I mean by a "list of possible end rhymes":

  • "ay" as in "bay": [ay, eigh, ei]
  • "i" as in "by": [y, eye, aye, ye]
  • "ah" as in "saw": [a, ah, aw]
  • "ot" as in "bot": [ot, ott, ought, aught]

Logical workthrough using an example:

  • Pre-requisite: User input: "Scott"
  • Step 1: Get user input [Result: "Scott"]
  • Step 2: Find length of user's input [Result: 5 characters long, aka has positions 0-4]
  • Step 3: Find location of first vowel [Result: first vowel is "o" at position 2]
  • Step 4: Select all letters after and including that vowel [Result: returns substring "ott"]
  • Step 5: Compare substring to possible end rhymes/spellings (Result: returns variable match for the "ot" end rhyme)
  • Step 6: Limit terminal-word choices for lines 3, 5, and 7 to subset of words with "ot" end rhyme [NB: this would be a pre-selected library of words already identified with that rhyme scheme]

My major roadblock is comparing the selected substring "ott" to my collection of possible end rhymes. If I arranged the end-rhymes like this:

var ay = ["ay", "eigh", "ei"];
var eye = ["y", "eye", "aye", "ye"];
var ah = ["a", "ah", "aw"];
var ot = ["ot", "ott", "ought", "aught"];

is it then possible to check to see if the substring matches any one of the options in the array? Would that be another place I might be able to use a regex?

1 Answers

For getting an ending, you could use a regular expression which looks either for zero or more of vowels followed by a vowel or y and the end of string or a group of vowels followed by non vowels and the end of the string.

function getEnding(word) {
    return (word.match(/[aeiou]*[aeiouy]$|[aeiou]+[^aeiou]+$/) || [''])[0];
}

console.log(['scott', 'bay', 'by', 'saw', 'bot', 'uncaught'].map(getEnding));

Related