NIKHIL C M
NIKHIL C M

Reputation: 4236

while loop is not working properly

I am writing code for my one of the exercises in freecodecamp.com called as Pig Latin problem. For a while loop it should stop executing the code inside it when the condition becomes wrong.For my case the while loop must stop executing the codes inside it when it finds that it seen a vowel in the charas array during iteration. I think my code is correct in my point of view, but while loop is not stopping execution when it sees a vowel instead it iterate through every element in the charas array.

Here is my code

function translatePigLatin(str) {
  var vowels = ['a','e','i','o','u'];
  var f="";
  var charas = str.split("");
  if(vowels.indexOf(charas[0])!==-1) {
      // vowel
    charas.push("w");
    charas.push("a");
    charas.push("y");
    f = charas.join("");
  } else {
    //if first letter  is a consonant or cluster of consonants
    var i = 0;
    while(vowels.indexOf(charas[i]) ===-1) {
     charas.push(charas[i]);
     charas.splice(i,1);
     i = i+1;
     }    
   charas.push('a');
   charas.push('y');
   f  = charas.join("");   
  }
  return f;
}

translatePigLatin("california");

Upvotes: 1

Views: 119

Answers (4)

Useless Code
Useless Code

Reputation: 12402

Your problem is that you increment i. You move the first element from the start of the array and then increment i you are skipping a letter because what was charas[1] is now charas[0] and what is charas[1] was charas[2].

If you step through the code and inspect the charas array you can see this happening:

Starting state:

["c", "a", "l", "i", "f", "o", "r", "n", "i", "a"]

"c" gets moved to the end i is incremented to 1

["a", "l", "i", "f", "o", "r", "n", "i", "a", "c"]

"l" is at position 1, so it gets moved to the end. i is incremented to 2

["a", "i", "f", "o", "r", "n", "i", "a", "c", "l"]

"f" is at position 2, so it gets moved to the end. i is incremented to 3

["a", "i", "o", "r", "n", "i", "a", "c", "l", "f"]

"r" is at position 3, so it gets moved to the end. i is incremented to 4

["a", "i", "o", "n", "i", "a", "c", "l", "f", "r"]

"i" is at position 4, the while condition is met, "aioniaclfr" will be returned.

If you just get rid of i and always check charas[0] it works like expected:

function translatePigLatin(str) {
  var vowels = ['a','e','i','o','u'];
  var f = "";
  var charas = str.split("");
  if(vowels.indexOf(charas[0]) !== -1) {
    // vowel
    charas.push("w");
    charas.push("a");
    charas.push("y");
    f = charas.join("");
  } else {
    //if first letter  is a consonant or cluster of consonants
    while(vowels.indexOf(charas[0]) === -1) {
     charas.push(charas[0]);
     charas.splice(0,1);
    }
    charas.push('a');
    charas.push('y');
    f = charas.join("");
  }
  return f;
}

document.getElementById('out').textContent = translatePigLatin("california");
<div id="out"></div>

As a side note, this type of while condition will lead to an infinite loop if someone passes in a string that is all consonants, it will just keep shuffling the letters around because it will never find a vowel to stop it. To avoid this, I would add another if condition to check for that to make sure it won't happen:

function translatePigLatin(str) {
  var vowels = ['a','e','i','o','u'];
  var f = "";
  var charas = str.split("");
  if (!str.match(/[aeiou]+/)) {
    // only consonants do something
     f = str + 'ay';
  } else if (vowels.indexOf(charas[0]) !== -1) {
    // vowel
    charas.push("w");
    charas.push("a");
    charas.push("y");
    f = charas.join("");
  } else {
    //if first letter  is a consonant or cluster of consonants
    while(vowels.indexOf(charas[0]) === -1) {
     charas.push(charas[0]);
     charas.splice(0,1);
    }
    charas.push('a');
    charas.push('y');
    f = charas.join("");
  }
  return f;
}

document.getElementById('out').textContent = translatePigLatin("wkrp");
<div id="out"></div>

/[aeiou]+/ is a regular expression meaning any vowel one or more times anywhere in the string the ! in !str.match(/[aeiou]+/) negates the result of match, so if there are no vowels in the string that branch of the if is followed.

Upvotes: 0

Weedoze
Weedoze

Reputation: 13943

The problem is that your are iterating AND modifying the same array at the same time

You can simplify your code like this

function translatePigLatin(str) {
  var vowels = ['a', 'e', 'i', 'o', 'u'];
  //start with vowel
  if (vowels.indexOf(str[0]) !== -1) {
    return str + "way";
  }

  var i = 0;
  var beforeVowel = "";
  var chars = str.split("");
  while (vowels.indexOf(chars[i]) === -1 && i < str.length) {
    beforeVowel += chars[i];
    i++;
  }
  return str.substring(i) + beforeVowel + "ay";
}

console.log(translatePigLatin("california"));
console.log(translatePigLatin("pig"));
console.log(translatePigLatin("eat"));

Upvotes: 0

Pugazh
Pugazh

Reputation: 9561

You haven't added the condition to exit the while loop, use i <= length of charas. Check below snippet.

function translatePigLatin(str) {
  var vowels = ['a', 'e', 'i', 'o', 'u'];
  var f = "";
  var charas = str.split("");

  if (vowels.indexOf(charas[0]) !== -1) {
    // vowel
    charas.push("w", "a", "y");
    f = charas.join("");
  } else {
    //if first letter  is a consonant or cluster of consonants
    var i = 0;
    var len = charas.length;
    while (vowels.indexOf(charas[i]) === -1 && i <= len) {
      charas.push(charas[i]);
      charas.splice(i, 1);
      i++;
    }
    charas.push('a', 'y');
    f = charas.join("");
  }
  return f;
}

console.log(translatePigLatin("california"));

Upvotes: 0

Alex Netrebsky
Alex Netrebsky

Reputation: 261

It works as work cause

 charas.push(charas[i]);
 charas.splice(i,1);
 i = i+1;

After the first iteration it move 'a' letter at the begging as result i == 1 (in second iteration) charas[i] refers to consonant 'l'.

Upvotes: 1

Related Questions