freeCodeCamp Algorithm Challenge Guide: Pig Latin

freeCodeCamp Algorithm Challenge Guide: Pig Latin
0

#1

:triangular_flag_on_post: Remember to use Read-Search-Ask if you get stuck. Try to pair program :busts_in_silhouette: and write your own code :pencil:

:checkered_flag: Problem Explanation:

You need to create a program that will translate from English to Pig Latin. Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an “ay”. If a word begins with a vowel you just add “way” to the end. It might not be obvious but you need to remove all the consonants up to the first vowel in case the word does not start with a vowel.

Relevant Links

:speech_balloon: Hint: 1

You will probably want to use regular expressions. This will allow you to convert the words easily.

try to solve the problem now

:speech_balloon: Hint: 2

If the first character is a vowel, then take that whole word and add ‘way’ at the end. Otherwise comes the tricky part, take the consonant(s) before the first vowel and move it to the end and add ‘ay’. This might be confusing but, it is not just the first consonant but all of them before the first vowel.

try to solve the problem now

:speech_balloon: Hint: 3

You will need to use everything you know about string manipulation to get the last part right. However, it can be done with substr alone.

try to solve the problem now

Spoiler Alert!

687474703a2f2f7777772e796f75726472756d2e636f6d2f796f75726472756d2f696d616765732f323030372f31302f31302f7265645f7761726e696e675f7369676e5f322e676966.gif

Solution ahead!

:beginner: Basic Code Solution:

function translatePigLatin(str) {
  // Create variables to be used
  var pigLatin = '';
  var regex = /[aeiou]/gi;

  // Check if the first character is a vowel
  if (str[0].match(regex)) {
    pigLatin = str + 'way';

  } else {

    // Find how many consonants before the first vowel.
    var vowelIndice = str.indexOf(str.match(regex)[0]);

    // Take the string from the first vowel to the last char
    // then add the consonants that were previously omitted and add the ending.
    pigLatin = str.substr(vowelIndice) + str.substr(0, vowelIndice) + 'ay';
  }

  return pigLatin;
}

// test here
translatePigLatin("consonant");

:rocket: Run Code

Code Explanation:

  • Make an empty string to hold your Pig Latin word.
  • Assign your appropriate regular expression to a variable.
  • If the first character is a vowel, just add way to end of string and return it.
  • If the first character is not a vowel:
    • Find number of consonants before first vowel with help of indexOf(), match() and regex.
    • Start Pig Latin string with first vowel till the end.
    • Add letters before first vowel to end of string.
    • substr() is used for string manipulation here.
    • Add ay to end of string and return it.

Relevant Links

:sunflower: Intermediate Code Solution:

function translatePigLatin(str) {
  function check(obj) {
      return ['a','i','u','e','o'].indexOf(str.charAt(obj)) == -1 ? check(obj + 1) : obj;
  }

  return str.substr(check(0)).concat((check(0) === 0 ? 'w' : str.substr(0, check(0))) + 'ay');
}

// test here
translatePigLatin("consonant");

:rocket: Run Code

Code Explanation:

  • This is a declarative as well as recursive approach to this problem.
  • check() is a function which checks for first letter of string to be in the array of vowels, ['a','i','u','e','o'].
  • In case of consonants, check() calls itself on the next characters until finding the first vowel.
  • It’ll return the index of whatever it finds to be the last initial consonant i.e., Schmidtsville’s would be 3.
  • Then, letters up until that index are removed from the string and concatenated with either that same chunk of removed string or w accordingly, and then ay regardless.

Relevant Links

:rotating_light: Advanced Code Solution:

function translatePigLatin(str) {
    var strArr = [];
    var tmpChar;

    // check if the char is consonant using RegEx
    function isConsonant(char) {
        return !/[aeiou]/.test(char);
    }

    // return initial str + "way" if it starts with vowel
    // if not - convert str to array
    if (!isConsonant(str.charAt(0)))
        return str + "way";
    else
        strArr = str.split("");

    // push all consonats to the end of the array
    while (isConsonant(strArr[0])) {
        tmpChar = strArr.shift();
        strArr.push(tmpChar);
    }
 // convert array to string and concatenate "ay" at the end  
 return strArr.join("")+"ay";
}

// test here
translatePigLatin("consonant");

:rocket: Run Code

Code Explanation:

  • isConsonant() is used to check if a character is a consonant.
  • If first character is vowel, add way to end of string and return it.
  • If first character is not a vowel:
    • Split string into array using split().
    • Push all consonants to end of array with help of shift() and push().
    • Convert array to string using join() and add ay to end of string. Return it.

Relevant Links

:rotating_light: Advanced Code Solution 2:

function translatePigLatin(str) {
  return str
    .replace(/^([aeiouy])(.*)/, '$1$2way')
    .replace(/^([^aeiouy]+)(.*)/, '$2$1ay');
}

// test here
translatePigLatin("consonant");

Code Explanation:

  • The first .replace() works only if the string begins with a vowel, in that case it adds way at the end of the string.
  • The second .replace() works only if the string begins with one or more consonants, in that case it moves them at the end of the string and adds ay at the end of it.

Relevant Links

:trophy: Credits:

If you found this page useful, you may say thanks to the contributors by copying and pasting the following line in the main chat:

Thanks @Rafase282 @sabahang @aganita @Hallaathrad @fergus.incoronato for your help with Algorithm: Pig Latin

:clipboard: NOTES FOR CONTRIBUTIONS:

  • :warning: DO NOT add solutions that are similar to any existing solutions. If you think it is similar but better, then try to merge (or replace) the existing similar solution.
  • Add an explanation of your solution.
  • Categorize the solution in one of the following categories — Basic, Intermediate and Advanced. :traffic_light:
  • Please add your username only if you have added any relevant main contents. (:warning: DO NOT remove any existing usernames)

See :point_right: Wiki Challenge Solution Template for reference.


Explain the uses of caret(^) in regex
Thank you very much
Pig Latin code explanation
#2

Thanks for sharing information!

BTW My code is following:

function translatePigLatin(str) {
  var newString = str + "way";
  
  if (/[qwrtypsdfghjklzxcvbnm]{1,}/i[Symbol.match](str[0])) {
  var firstConsonants = /[qwrtypsdfghjklzxcvbnm]{1,}/i[Symbol.match](str);
  var length = firstConsonants[0].length;
  var newStr = str.substr(length) + firstConsonants + "ay";
  return newStr; 
    
  }
  
  return newString;

}

translatePigLatin("glove");

#3

#4

#5

For what it’s worth, my solution is similar to the intermediate one, but I used String.prototype.search() to find the index of the first vowel:

function translatePigLatin(str) {
  var firstVowel = str.search(/[aeiou]/);
  
  return firstVowel === 0 ? str + 'way' : str.substr(firstVowel) + str.substr(0, firstVowel) + 'ay';
}

#6

In the advanced code solution :rotating_light: , and also in @vkg’s solution, the regEx should be /[aeiou]/i because without the i modifier the test will be case sensitive and strings starting with a capital vowel will be translate as consonant starting (e.g. translatePigLatin(“Airway”); will return “irwayAay” instead of “Airwayway”).


#7

Didn’t see any solution with just string.prototype.replace(); so I thought I’d add mine.

function translatePigLatin(str) {
  if (["a","e","i","o","u"].indexOf(str.charAt(0)) != -1){
    return str += "way";
  }
  return str.replace( /([^aeiou]*)([aeiou]\w*)/ , "$2$1ay");
}

translatePigLatin("consonant");

#8

As if this writing, the description on freecodecamp for this exercise states:

“Input strings are guaranteed to be English words in all lowercase.”


#9

This should be the recommended advanced solution. Not only is it concise and easy to read, but it also works. Whereas the other solutions presented fail on consonant only words, such as ‘my’ or ‘TV’.


#10

my version of pig latin. i did not use regular express. however, the regular express solution are pretty sweet!

function translatePigLatin(str) {
var vowels= [‘a’,‘e’,‘i’,‘o’,‘u’], index=0;

 if(vowels.indexOf(str[index])!== -1){  //initial edge case
     return str+"way";
 }
 for(index=1;index<str.length;index++){
     if(vowels.indexOf(str[index]) !==-1){//first vowel found
         break;
    }
 }

return str.slice(index,str.length)+str.slice(0, index)+“ay”;
}


#11

Some good solutions on here. Mine’s a little different, so I’ll post it too. I used String.prototype.replace(), with a function rather than direct string replacement:

function translatePigLatin(str) {
  return str.replace(/(^[^aeiou]*)(\w*)/, function(match, p1, p2){
    return p2 + (p1 ? p1 : 'w') + 'ay';
  })
}

edit to add explanation:
Regarding the arguments passed to the inline function:

  • match in this case only serves as a placeholder since it is always the first argument passed by replace( ) but is not actually used in the function (with this regex match is always the whole word (given the input string is stipulated to be an English word in lowercase).
  • p1 is the first parenthesized submatch string ^[^aeiou]* , i.e. zero or more non-vowels at the beginning of the word. Ex. for ‘glove’ p1 = ‘gl’ and for ‘algorithm’ p1 = “”.
  • p2 will be all the characters in the word that were not captured by p1. Ex. ‘glove’ p2 = ‘ove’ and for ‘algorithm’ p2 = ‘algorithm’.

#12

The Basic solution should be extended by an if construct that first checks if there are any matches before it tries to assign them to vowelIndice. Its a pretty big oversight imho.

Otherwise the solution is perfectly fine.


#13

Hello, all your solutions looks very clever, my solution is probably a bit basic, because I use only for loops and if’s to check for the vowels. And I haven’t heard of regular expressions prior to reading the solution. So what do you think of my solution?

      function translatePigLatin(str) {

      var vowels = ["a","e","i","o","u"];
      var strArr = str.split("");
      var index;

      // Look for the vowel index in a string
      for(var k = 0; k < strArr.length; k++){
        for(var i = 0; i < vowels.length; i++){
          if(strArr[k] === vowels[i]){
            if(index === undefined){
              index = strArr.indexOf(strArr[k]);
            }
          }
        }
      }

      // if vowel is not the first letter use pig latin method
      if(index !== 0){
        var sliced = str.slice(0, index);
        str = str.slice(index) + sliced + "ay";
      }else {
        str = str + "way";
      }

      return str;
    }

    translatePigLatin("consonant");

#14

Another solution. Using indexOf, charAt and substr functions.

function translatePigLatin(str) {
var vow = ['a','e','i','o','u'];
if(vow.indexOf(str.charAt(0)) !== -1){
  str += "w";
}
while(vow.indexOf(str.charAt(0)) == -1){
  str = str.substr(1) + str.charAt(0);
}
return str += "ay";
}
//test here
translatePigLatin("california");

#15

How should I understand this return statement? Does it return

['a','i','u','e','o'].indexOf(str.charAt(obj)) == -1 ? check(obj + 1) : obj;

or does it just return
check(obj + 1) or obj depending on the result of ['a','i','u','e','o'].indexOf(str.charAt(obj)) == -1 ?


#16

My solution is ultra-basic so I appreciate these threads so I can take notes for improving my approach for later exercises.

That said, I have to point out that none of the solutions I’ve read in this thread so far appear to address the ‘y’ character; i.e., the word ‘dynamic’ in pig latin should be ‘ynamicday’ but unless I’m missing something, every solution here would return ‘amicdynay’. Again, unless I’m missing something.

In any case, here’s my red-headed stepchild:


function translatePigLatin(str) {
  var vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
  var str1 = "";
  
  if(vowels.indexOf(str.charAt(0)) !== -1 && str.charAt(0) !== "y") {
    str1 += str + "way";
  } else if(str.charAt(0) === "y") {
    str1 += str.slice(1) + "yay";
  } else {
    for(var i = 0; i < str.length; i++) {
      if(vowels.indexOf(str.charAt(i)) !== -1) {
        return str1 += str.slice(i) + str.slice(0, i) + "ay";
      }
    }
  }
  str = str1;
  return str;
}


#17

Ladies and Gentlemen, as a long time reader but a first time poster on this forum I present to you the world most inelegant code that solve the pigLatin algorithm.

function translatePigLatin(str) {
var chr = "";
for (var i = 0; i < str.length; i++) {
    chr = str.charAt(i);
    if (chr == "a" || chr == "e" || chr == "i" || chr == "o" || chr == "u") {
        break;
    }
}
//console.log(str.indexOf(chr)); //this gives the position of the first vowel in the word.
if (chr === str[0]) {
    str = str + "way";
    console.log(str); //use return on FCC
} else {
    str = str.split("");
    //the consonant or consonant clusters are stored in removed
    var removed = str.slice(0, str.indexOf(chr)).join("");
    //the rest of the word starting with the vowel is stored in vowelInitial
    var vowelInitial = str.slice(str.indexOf(chr)).join("");
    var allTogether = vowelInitial + removed + "ay";

    console.log(allTogether); //use return on FCC
}

}


#18

Solution using just match and replace with regex

function translatePigLatin(str) {
  if(str.match(/^[aeiou]/)){  //starts with vowel
    return str.replace(/(.+)/,"$1way");
  }else if(str.match(/[aeiou]/g)){ //starts with consonant or consonant cluster
    return str.replace(/(^[^aeiou]+)(.+)/g,"$2$1ay");
  }else{ //all consonants 
    return str + "ay";
  }
}

#19

My solution

function translatePigLatin(str) {
  var strArr = str.split('');
  var frstLet = strArr[0];
  var pigArr = [];
  var i = 1;
  
  function checkVowel(x) {
    return (x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u');
  }

  if (checkVowel(frstLet)) {
    strArr.push('way');
    str = strArr.join('');
  } else {
    pigArr.push(frstLet);
    while (!checkVowel(strArr[i])) {
      pigArr.push(strArr[i]);
      i++;
    }
    pigArr.push('a', 'y');
    pigArr = pigArr.join('');
    str = strArr.slice(i).join('') + pigArr;
  }
  
  return console.log(str);
}

#20

My solution:
function translatePigLatin(str) {
var vowel = [“a”,“o”,“i”,“e”,“y”,“u”];
var cluster = str.charAt(0) + str.charAt(1);
if (vowel.indexOf(str[0]) !== -1) {
return str + ‘way’;
}
else if (vowel.indexOf(str[0]) == -1 && vowel.indexOf(str[1]) == -1) {
return str.substring(2) + cluster + ‘ay’;
}
else{
return str.slice(1) + str[0] + ‘ay’;
}
}