This Javascript loop is taking down my browser. Any idea why?

Asked

Viewed 161 times

3

I’m solving the following coderbyte Problem.com:

Using the Javascript language, have the Function Runlength(str) take the str Parameter being passed and Return a 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 splice the counter variable, which counts how many times a letter was repeated, after each of the repeated letters, and remove the occurrences of the repeated letter.

  • 3

    Your question seems to have come truncated.

  • I didn’t get it. How so cracked?

  • 1

    Truncada. "I know counter manipulation is ..." does not have a predicate.

  • Corrected! Thank you.

3 answers

6

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

I recommend that you define a variable with the str.length, then if the loop never ends (infinite loop) why the value of length always increases 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 present the expected result of its algorithm, it was only to explain how to avoid browser freezing due to infinite loop, to "compress" the 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>

  • 1

    The problem is that this code is still not working, right? I mean, would it need some kind of correction i += counter.toString() immediately after str.splice, and yet the code will discard the last run string.

  • @ctgPi I had not noticed, I focused on answering the problem of probable freezing, I will test thank you.

  • Yes, so the +1 (and anyway you answered exactly what was asked).

  • 1

    Now that you don’t change str, the j or is no longer needed or should have a better name, like strLength, if you’re saving it to save access to the attribute.

  • @ctgPi Thanks, already edited, also used the typeof to check if it is a string.

  • @Guilhermenascimento I made a strlen variable, as you suggested, and now he’s pointing TypeError: Cannot read property 'toString' of undefined :(

  • @Kvera tested both codes and no such error happens, maybe you have copied or deleted something, or changed the names of the variables. Note that the second code the algorithm works, the first code was only to explain the reason for freezing. I edited the answer, see that both codes have buttons with the text "Run code snippet", please test both.

Show 2 more comments

4

Although @Guilhermenascimento mentioned his 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

  • 3

    i == str.length is not always false?

  • Truth @ctgPi is that I had started with a logic and changed

  • @ctgPi Corrected and thank you :)

2


As already said was the problem of the counter always increment what left the loop "infinite"

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;
}
  • What your code returns to the string "aba"?

  • no, returns what the algorithm asks for.

  • The answer to "aba" should be "1a1b1a"; your program returns "2a1b".

Browser other questions tagged

You are not signed in. Login or sign up in order to post.