Jason Holt
Jason Holt

Reputation: 93

Browser Freezing on Loop Run (JavaScript)

I am trying to rebuild a paragraph of words randomly without repeating the same word in JavaScript:

var  para = 'dashing through the snow' +
        ' in a one horse open sleigh' +
        ' over the fields we go' +
        ' laughing all the way';
console.log(para);
function getRandomNumber(min, max) 
{
     return Math.floor(Math.random() * (max - min)) + min;
}

var words = para.split(' ');
var newPara = '';

for(var i = 0; i < words.length - 1; i++)
{
  var curWord = words[getRandomNumber(0,words.length - 1)];

  if(newPara.indexOf(curWord) == -1)
  {
    newPara += curWord + ' ';
    console.log(newPara);
  } else
  {
    i--;
  }

}

The code splits a paragraph into an array of words (19 in all). I then use a loop to loop through this array and select a word at random, checking if the word has been added to the newPara string. If it has not, I add it. If it has, I subtract 1 from the loop run. The problem is that the script causes the browser to freeze when I use the else statement to subtract one from the loop. Any help on this problem is appreciated.

Based on comments I made this edit:

if(newPara.length <= words.length)
    {
    if(newPara.indexOf(curWord) == -1)
    {
      newPara += curWord + ' ';
      console.log(newPara);
    } else
    {
      i--;
    }
  }

However, I am still getting the same error.

Upvotes: 2

Views: 250

Answers (3)

Yichong
Yichong

Reputation: 727

Try this code:

var para = 'dashing through the snow' +
    ' in a one horse open sleigh' +
    ' over the fields we go' +
    ' laughing all the way';
var words, newPara = '';
console.log(para);

words = para.split(' ');

words.sort(function(a, b) {
    return 0.5 - Math.random();
});

newPara = words.join(' ');
console.log(newPara);

The problem in your code is that some word in your para repeats several times, like the word 'the' occurs 3 times, it will never meet the condition: i === words.length - 1.

var  para = 'dashing through the snow' +
    ' in a one horse open sleigh' +
    ' over the fields we go' +
    ' laughing all the way';

There is also a bug in your random number generating algorithm, which makes it extremely difficult to get the last number words[words.length-1], changing getRandomNumber(0, words.length - 1) to getRandomNumber(0, words.length) will make it work.

Upvotes: 0

Kielstra
Kielstra

Reputation: 535

What you are creating is an infinite loop. If a word which is already used is picked by the random number generator for 2 more times, your loop counter is subtracted by 2. Eventually when all words are used (lets assume that there are only chosen 1 or 2 times) your i is always smaller than words.length (hence, the condition is never met).

A possible solution is to save the length of the paragraph in a variable and use that in your loop condition. Then for every word you choose, you remove it from the words array.

This wil not end up in a infinite loop and will also minimize your number of iterations, since there are no more misses when trying to find a word.

Upvotes: 0

Wild Beard
Wild Beard

Reputation: 2927

The solution I came up with is to work backwards from words.length to 0 and remove the word from the array if it has already been used.

Fiddle

var para = 'dashing through the snow' +
  ' in a one horse open sleigh' +
  ' over the fields we go' +
  ' laughing all the way';

function getRandomNumber(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

var words = para.split(' ');
var newPara = '';

for (var i = words.length; i > 0; i--) {

  var rand = getRandomNumber(0, words.length - 1),
    curr = words[rand];

  if (newPara.indexOf(curr) == -1) {
    newPara += curr + ' ';
    words.splice(rand, 1);
  }

}

console.log(newPara);

Upvotes: 2

Related Questions