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.
You will probably want to use regular expressions. This will allow you to convert the words easily.
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.
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.
Solutions
Solution 1 (Click to Show/Hide)
function translatePigLatin(str) {
let consonantRegex = /^[^aeiou]+/;
let myConsonants = str.match(consonantRegex);
return myConsonants !== null
? str
.replace(consonantRegex, "")
.concat(myConsonants)
.concat("ay")
: str.concat("way");
}
translatePigLatin("consonant");
Code Explanation
start at beginning and get longest match of everything not a vowel (consonants)
if regex pattern found, it saves the match; else, it returns null
if regex pattern found (starts with consonants), it deletes match, adds the match to the end, and adds “ay” to the end
if regex pattern not found (starts with vowels), it just adds “way” to the ending
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 if (str.match(regex) === null) {
// Check if the string contains only consonants
pigLatin = str + "ay";
} 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");
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.
function translatePigLatin(str) {
if (str.match(/^[aeiou]/)) return str + "way";
const consonantCluster = str.match(/^[^aeiou]+/)[0];
return str.substring(consonantCluster.length) + consonantCluster + "ay";
}
// test here
translatePigLatin("consonant");
Code Explanation
First, check to see if the string begins with a vowel.
The regex looks at the beginning of the string ^ for one of the specified characters [aeiou]
If it does, you only need to return the original string with “way” appended on the end.
If the string does not start with a vowel, we want to build a string which contains every consonant before the first vowel in the provided string.
To do this, look at the beginning of a string ^ for one or more characters + NOT specified [^aeiou].
If there is a match (and in this case, there always will be), match() returns an Array with the matched string as the first element, which is all we want. Grab it with [0].
Now, we can start building our Pig Latin string to return. This can be built in three parts:
The first part contains all of the characters in the original string, starting from the first vowel. We can easily get these characters by creating a substring of the original string, with its starting index being the first vowel.
The second part contains the consonant string we just built. (If you add the second and first parts of this string together, you will get the original string.)
function translatePigLatin(str) {
return str
.replace(/^[aeiou]\w*/, "$&way")
.replace(/(^[^aeiou]+)(\w*)/, "$2$1ay");
}
// test here
translatePigLatin("consonant");
Code Explanation
Use replace() on the string, using a regular expression to check if the first letter is a consonant and adding way at the end in this case. If the first letter is a consonant nothing will happen at this point.
Use replace() again to check for consonants at the beginning of the word and to move it or them to the end of the word and add ay at the end.
In the advanced code solution , 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”).
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’.
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:
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’.
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.
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");
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.
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
}