DEV Community

Viren B
Viren B

Posted on • Originally published at virenb.cc

Solving "Pig Latin" / freeCodeCamp Algorithm Challenges

Pig Latin

Let's solve freeCodeCamp's intermediate algorithm scripting challenge, 'Pig Latin'.

Starter Code

function translatePigLatin(str) {
  return str;
}

translatePigLatin("consonant");

Instructions

Pig Latin is a way of altering English Words. The rules are as follows:

- If a word begins with a consonant, take the first consonant or consonant cluster, move it to the end of the word, and add "ay" to it.

- If a word begins with a vowel, just add "way" at the end.


Translate the provided string to Pig Latin. Input strings are guaranteed to be English words in all lowercase.

Test Cases

translatePigLatin("california") should return "aliforniacay".
translatePigLatin("paragraphs") should return "aragraphspay".
translatePigLatin("glove") should return "oveglay".
translatePigLatin("algorithm") should return "algorithmway".
translatePigLatin("eight") should return "eightway".
Should handle words where the first vowel comes in the middle of the word. translatePigLatin("schwartz") should return "artzschway".
Should handle words without vowels. translatePigLatin("rhythm") should return "rhythmay".

Our Approach

The instructions for this challenge are short and to the point.

  • Our one input is str, a string. Looking at the test cases, they are all lower cased letters, no white spaces or non letter characters.

  • We must return a string.

  • We need to check what str begins with. If it is a consonant (non-vowel), take the consonant or streak of consonant before we find a vowel, move it to the end of the word plus 'ay'. If word begins with a vowel, just add 'way' at the end. Looks like we'll need some if/else logic.

Looks like we're going to have to dive into Regular Expressions again!

We are working with vowels and non-vowels. Vowels are a, e, i, o, u. I think we will make a RegEx which contains all letters but the vowels. We can use a string method, match(), to see if the word begins with a vowel.

String.match() on MDN

match() will return you an array of the characters which matches the RegEx you provide. For example -

'hello world'.match(/o/g);
// Array ['o', 'o']

I think using match() is good because once we have an array, it would be easy to add on 'way' or 'ay' to the array.

If we (try) to begin to build our RegEx for vowels, we would start off with something like [aeiou]. After a little exploring with how to build it, it might be better to build a RegEx for consonants and not the vowels. So a cononant is every letter which isn't a vowel. Reading MDN documentation again, ^ will be of use to us.

RegEx ^

Reference

So, [^aeiou] should give us consonants. Let's try quickly -

'tacocat'.match(/[^aeiou]/g);
// Array [ 't', 'c', 'c', 't' ]

So we have two more things to have to our regular expression. We will be using ^ again as it is used for the beginning of the string. Again, a quick test -

// Testing out /^[^aeiou]/g (beginning letter should be not be a vowel)

/^[^aeiou]/g.test('tacocat')
// true (the beginning letter is not a vowel)

// One more..
/^[^aeiou]/g.test('ocean')
// false (the beginning letter is a vowel)

The last concern in our RegEx, after re-reading the instructions, is to worry about a consonant cluster. If we have a test case like 'breakfast', we need to add 'br' and not just 'b' to the end of the word. We will add a '+' to the end of the expression so it just doesn't stop after one matching case.

'chronic'.match(/^[^aeiou]/g)
// Array [ 'c']

// With '+'
'chronic'.match(/^[^aeiou]+/g)
// Array [ 'chr' ]

So let's start coding our solution. Lets first save our new regular expression in a variable:

const regex = /^[^aeiou]+/g;

Once we've declared our regex variable, the next thing I want to do is find out all the consonants from str and save them in their own variable. We will use match() for this.

const consonants = str.match(regex);

Remember consonants is an array.

Now comes in our if/else logic to see what str begins with.

if (consonants is empty) {
    add 'way' to str
}
else {
    replace beginning of str with '', add consonants and then the 'ay'
}

If consonants is null we can just use concat() too add 'way' to str and save str.

// For our cases that begin with a vowel
if (consonants === null) {
  str = str.concat('way')
}

If our test case begins with a consonant or consonant cluster -

else {
  str = str.replace(regex, '').concat(consonants).concat('ay')
}

We're saving str to str, replacing the beginning with an empty string, then adding the letters we removed into consonants then adding 'ay' at the end per instructions.

And as always, make sure to return a value.

Our Solution

function translatePigLatin(str) {
  const regex = /^[^aeiou]+/g;
  const consonants = str.match(regex);
  if (consonants == null) {
    str = str.concat('way');
  }
  else {
    str = str.replace(regex, '').concat(consonants).concat('ay');
  }
  return str;
}

translatePigLatin("consonant");

Links & Resources

'Pig Latin' Challenge on fCC

freeCodeCamp

Donate to FCC!

Solution on my GitHub

Thank you for reading!

Top comments (2)

Collapse
 
ttatsf profile image
tatsuo fukuchi • Edited

You can make it simpler to use the "early-return" technique.

function translatePigLatin(str) {
  const regex = /^[^aeiou]+/g;
  const consonants = str.match(regex);
  if (consonants == null) {
    return str.concat('way');
  }
  else {
    return str
      .replace(regex, '')
      .concat(consonants)
      .concat('ay');
  } 

And, another way using ordinally array-like methods (or, not using the regex):

const innerTPL = head => tail => 
  tail === "" ? 
    head === "" ? ""
    : head + "ay"
  : "aeiou".includes(tail[0]) ? 
    head === "" ? tail + "way"
    : tail + head + "ay"
  : innerTPL(head + tail[0])(tail.slice(1))  

const translatePigLatin = innerTPL("")
Collapse
 
saraarian profile image
saraarian

Hi,
Just wanted to thank you for the full explanation of the code. Without it, I could have got stuck forever.