More efficient loops to generate unpronounceable words I wanted to write a function to generate only unpronounceable words. I realised afterwards that the same thing could probably be achieved by just taking out the vowels. Regardless, I feel that there is probably a better way to iterate through the syllable checking.

function unpronouncable(length) {
    var twoLetters = ['aa','ae','ag','ai','ar','ao','as','aw','ay','ba','da','de','ed','ef','eh','ei','em','en','er','et','ex','fa','fe','fu','gi','go','hm','ho','so','id','ie','jo','ka','ki','ku','lo','mi','mm','mu','na','ne','nu','od','oe','oi','om','op','os','os','oy','pe','pi','qi','re','se','ta','ti','ut','wo','xi','xi','ya','yu','za','zo','co','my','qu','ge','ro','ra','xa','wa'];
    var threeLetters = ['thm','css','dvd','buh','bad','rue','cun','pub','puk','pul'];

    var letters = "abcdefghijklmnopqrstuvwxyz";
    var string = "";
    for (var i = 0; i &lt; length; i += 1) {
        string += letters[Math.floor(Math.random() * letters.length)];
    }

    function generate() {
        for (var j = 0; j &lt; string.length; j += 1) {
            var test = string.slice(j,j+2);
            for (var k = 0; k &lt; twoLetters.length; k += 1) {
                if (twoLetters[k] === test) {
                    console.log('Has two letter syllable');
                    return unpronouncable(length);
                }
            }
        }
        for (var j = 0; j &lt; string.length; j += 1) {
            var test = string.slice(j,j+3);
            for (var k = 0; k &lt; twoLetters.length; k += 1) {
                if (threeLetters[k] === test) {
                    console.log('Has three letter syllable');
                    return unpronouncable(length);
                }
            }           
        }

        return string;
    }
    return generate();
}

console.log(unpronouncable(8));
Copy Pasting

If you are copy-pasting code, it is a sign that you should write it differently (your two for loops are quite obviously copy pasted).

Bug

I'm pretty sure that here:

        for (var k = 0; k &lt; twoLetters.length; k += 1) {
            if (threeLetters[k] === test) {


you meant to change it to k &lt; threeLetters.length;.

Solution

Instead of copy-pasting the for loop code, extract it to a function:

function generateHelper(string, array, charCount) {
    for (var j = 0; j &lt; string.length; j += 1) {
        var test = string.slice(j,j+charCount);
        for (var k = 0; k &lt; array.length; k += 1) {
            if (array[k] === test) {
                console.log('Has ' + charCount + ' letter syllable');
                return unpronouncable(length);
            }
        }
    }
}


Coding Style

i++

It is customary to write j++ instead of j += 1 in loops.

loop variable

It is also customary to use i as primary loop variable and j as secondary variable in case the loop is nested inside another loop. As your j-loops in generate are not nested, I would use i for them, and then j instead of k for the nested loop.

Call of return generate();

return should generally be at the end of a function, but in this case, I would pull it up in front of the generate function definition. It is easier to overlook at the bottom.

But the whole generate method seems unnecessary. Couldn't you just remove these lines:

function generate() {
}
return generate();


I don't mean the code inside the function, just the function definition and the function call.

General Approach

You already mentioned that this is probably not the best approach, so I'm not going to say too much about it. Generally, I would probably go with an iterative solution as most of the time they are easier to understand and faster as well.

An example of an iterative approach might look like this:

function unpronouncable(length) {
    // filter these out
    var twoLetters = ['aa', 'ae', 'ag', 'ai', 'ar', 'ao', 'as', 'aw', 'ay', 'ba', 'da', 'de', 'ed', 'ef', 'eh', 'ei', 'em', 'en', 'er', 'et', 'ex', 'fa', 'fe', 'fu', 'gi', 'go', 'hm', 'ho', 'so', 'id', 'ie', 'jo', 'ka', 'ki', 'ku', 'lo', 'mi', 'mm', 'mu', 'na', 'ne', 'nu', 'od', 'oe', 'oi', 'om', 'op', 'os', 'os', 'oy', 'pe', 'pi', 'qi', 're', 'se', 'ta', 'ti', 'ut', 'wo', 'xi', 'xi', 'ya', 'yu', 'za', 'zo', 'co', 'my', 'qu', 'ge', 'ro', 'ra', 'xa', 'wa'];
    var threeLetters = ['thm', 'css', 'dvd', 'buh', 'bad', 'rue', 'cun', 'pub', 'puk', 'pul'];

    // generate a new string until one is found that does not contain the filters
    var generatedString = "";
    var done = false;
    while (!done) {
        generatedString = generate(length);
        done = !contains(generatedString, twoLetters, 2) &amp;&amp; !contains(generatedString, threeLetters, 3);
    }
    return generatedString;

    // generates a random string with given length
    function generate(length) {
        var letters = "abcdefghijklmnopqrstuvwxyz";
        var string = "";
        for (var i = 0; i &lt; length; i++) {
            string += letters[Math.floor(Math.random() * letters.length)];
        }
        return string;
    }

    // returns true if string contains any characters in the stringArray.
    function contains(string, stringArray, charCount) {
        for (var k = 0; k &lt; stringArray.length; k++) {
            if (string.indexOf(stringArray[k]) &gt; -1) {
                console.log('Has ' + charCount + ' letter syllable');
                return true;
            }
        }
        return false;
    }
}
console.log(unpronouncable(8));


You could also replace the done = [...] assignment with two if statements, which might be easier to read.

Also: your approach with iterating over the string and using splice is quite complicated. Just use string.indexOf(stringArray[k]) &gt; -1; to check if a string contains another string.

And just out of curiosity: how would you pronounce css or dvd?