This Javascript loop is dropping my browser. Any idea why?

3

I'm solving the following coderbyte.com challenge:

  

Using the JavaScript language, have the function RunLength (str) take   the str parameter being passed and return to the compressed version of the   string using the Run-length encoding algorithm. This algorithm works   by taking the occurrence of each repeating character and outputting   that number along with a single character of the repeating sequence.   For example: "wwwggopp" would return 3w2g1o2p. The string will not   contain any numbers, punctuation, or symbols.

To do the RunLength algorithm, I wrote the following code:

function RunLength(str) { 

   str = str.split(""); 

   var counter = 1;

   for (var i=1; i<=str.length; i++) {

            if (str[i] === str[i-1]) {
                counter ++;
            } else {
                str.splice(i-1, counter-1, counter.toString());
                counter = 1;
            }   

   }

   return str

}

The idea was to insert the counter variable with splice, which counts how many times a letter was repeated after each of the repeated letters, and remove the occurrences of the repeated letter.

    
asked by anonymous 22.06.2015 / 20:36

3 answers

2

As I said it was the problem of the counter always incrementing what left the "infinite" loop

I changed the algorithm to use regular expressions

function RunLength(str) {
    var r = '';
    while (str.length > 0) {
        var current = new RegExp(str[0] + '+' );
        var length = str.match(current).toString().split('').length;
        r += length.toString() + str.match(current)[0][0];
        str = str.replace(str.match( current )[0], '');
    }

    return r;
}
    
22.06.2015 / 21:34
6

This occurs because at each loop it takes the value of str.length again, but at each loop the length of the str is updated and probably always increases when using str.splice .

I recommend that you define a variable with str.length , so if the loop never ends (loop infinite) because the value of length always increases the browser freezes.

How to set the variable:

function RunLength(str) { 

   str = str.split(""); 

   var counter = 1;

   for (var i = 1, strLen=str.length; i <= strLen; i++) {

            if (str[i] === str[i-1]) {
                counter++;
            } else {
                str.splice(i-1, counter-1, counter.toString());
                counter = 1;
            }   

   }

   return str

}

function testCase(str) {
    document.getElementById("mostrar").innerHTML = RunLength(str).join("");
}
<button onclick="testCase('wwwoopjj')">Testar wwwoopjj</button>
<button onclick="testCase('wwwggopp')">Testar wwwggopp</button>
<div id="mostrar"></div>

Note that the previous code does not show the expected result of your algorithm, it was just to explain how to avoid browser freezing due to the infinite loop, to "compress" strings with repetition, you can use something like (based on SOpt ):

function RunLength(str) {
    if (typeof str !== "string") {
        return "";
    }

    var builder = "";

    var count = 1;
    var prev = str[0];
    var current;

    for (var i = 1, strLen = str.length; i < strLen; i++) {
        current = str[i];
        if (current === prev) {
            count++;
        } else {
            builder += count + "" + prev;
            count = 1;
        }
        prev = current;
    }
    builder += count + "" + prev;
    return builder;
}

function testCase(str) {
    document.getElementById("mostrar").innerHTML = RunLength(str);
}
<button onclick="testCase('wwwoopjj')">Testar wwwoopjj</button>
<button onclick="testCase('wwwggopp')">Testar wwwggopp</button>
<div id="mostrar"></div>
    
22.06.2015 / 21:06
4

Although @GuilhermeNascimento has talked about your problem, the method splice makes your loop infinite, I'll post my solution:

function RunLength(str) { 

   str = str.split(""); 
   var strRetorno = "";
   var counter = 1;

   for (var i=0; i<str.length; i++) {
       if (str[i] != str[i+1]) {
            strRetorno += (counter) + str[i];
            counter = 1;
       } else {
            counter ++;
       }   

   }

   return strRetorno;

}

RunLength("wwwggopp");
  

3w2g1o2p

    
22.06.2015 / 21:14