John Allison
John Allison

Reputation: 367

While loop not properly breaking

I'm trying to generate a line of text that does not exceed a certain number of syllables in JavaScript running in Node. I have made the following function using a library syllable:

function generateLine(maxSyllableLength) {
    let line = "";
    let numSyllables = 0;

    /* generate line 
    while current number of syllables is less than the max:
        get a new word
        if the new word's syllables + the current number of syllables is less than the max:
            add the new word to the line
            add the new word's syllables to syllable count
    */
    while(numSyllables <= maxSyllableLength) {
        let word = randomWord();
        if(syllable(word) + numSyllables < maxSyllableLength) {
            line += word;
            numSyllables += syllable(word);
        }
    }
}

I expect it to break but it just runs forever and stalls Firefox when executed on Node. For reference, syllable(word) returns the number of syllables in word

randomWord() returns a, well, random word (a lot of them) and I am testing the function with maxSyllableLength = 5.

Full code:

var buzzwords = require('buzzwords')
var syllable = require('syllable')

/* constants for syllables in a haiku */
const LINE_ONE_THREE = 5;
const LINE_TWO = 7;

export default function Buzz() {
    /* generate line 1 */
    let lineOne = generateLine(5);
    console.log(lineOne); // debug

    /* render */
    return (
        <p id="test">{test}</p>
    );
}

function randomWord() {
    /* index of word we will pick out */
    let index = Math.floor((Math.random() * buzzwords.length) + 1); 

    /* pull a word from the array using that index */
    let word = buzzwords[index];
    return word;
}

function generateLine(maxSyllableLength) {
    let line = "";
    let numSyllables = 0;

    /* generate line 
    while current number of syllables is less than the max:
        get a new word
        if the new word's syllables + the current number of syllables is less than the max:
            add the new word to the line
            add the new word's syllables to syllable count
    */
    while(numSyllables <= maxSyllableLength) {
        let word = randomWord();
        if(syllable(word) + numSyllables < maxSyllableLength) {
            line += word;
            numSyllables += syllable(word);
        }
    }
}

Upvotes: 0

Views: 77

Answers (2)

3limin4t0r
3limin4t0r

Reputation: 21110

This endless loop seems to have a pretty simple explanation.

Assuming the following scenario:

  • maxSyllableLength is set to 4.
  • randomWord() always returns a random word of 2 syllables.

The first iteration numSyllables will be 0, matching the criteria to stay in the while-loop. syllable(word) + numSyllables will be 2, matching the if criteria. The line is extended with a random word and numSyllables is incremented accordingly.

The second iteration numSyllables will be 2, matching the criteria to stay in the while-loop. syllable(word) + numSyllables will be 4, not matching the if criteria. The loop starts over since the while-loop criteria still matches. Since nothing is changed the while-loop will go infinite at this point.

Summarized your while-loop will be infinite because numSyllables must be smaller or equal to the max, but can never exceed the max because syllable(word) + numSyllables must be lower than the max to increment the current values.

Upvotes: 1

patto
patto

Reputation: 11

In the line

if(syllable(word) + numSyllables < maxSyllableLength)

if numSyllables goes over the amount allocated, the loop needs to break, because now numSyllables is not able to go over maxSyllableLength so you need to not put the line

numSyllables += syllable(word)

within the if statement.

Upvotes: 1

Related Questions