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.
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.
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
Thank you for reading!
Top comments (2)
You can make it simpler to use the "early-return" technique.
And, another way using ordinally array-like methods (or, not using the regex):
Hi,
Just wanted to thank you for the full explanation of the code. Without it, I could have got stuck forever.