PigLatin Issue with substr() and slice() - javascript

OBJECTIVE
Given a string, translate the string into PigLatin (if the string starts with a vowel, append "way" to end of string - else look for the first vowel and take all preceding letters and place on the end of str, add "ay").
CODE
function translate(str) {
//list vowels
var vowel = ['a', 'e', 'i', 'o', 'u'];
//if first letter = vowel, add 'way' to end of sentence
// else return all letters before first vowel and append to end (with 'ay')
for (var i = 0; i < str.length; i++) {
if (vowel.indexOf(str[0]) > -1) {
return str + 'way';
} else {
return str.substr(i+1) + str.slice(0,i+1) + 'ay';
}
}
}
translate("dresser");
QUESTIONS
The aforementioned code works for cases such as "algorithm" and "desk", but failed with "glove" - leading me to believe the problem is around .substr() or .slice(). Additional investigation believes this is a logic error. Any help is appreciated!

The problem is that your code will always return from the loop during the first iteration. i will never be greater than 0.
What you should do (for starters) is remove the check from inside the loop. Like this:
function translate(str) {
//list vowels
var vowel = ['a', 'e', 'i', 'o', 'u'];
//if first letter = vowel, add 'way' to end of sentence
if (vowel.indexOf(str[0]) > -1) {
return str + 'way';
}
// else return all letters before first vowel and append to end (with 'ay')
for (var i = 0; i < str.length; i++) {
if (vowel.indexOf(str[i]) > -1) {
return str.substr(i) + str.slice(0,i) + 'ay';
}
}
}
This code should do the trick.

You are returning a value without testing if the character is a vowel.
function translate(str) {
//list vowels
var vowel = ['a', 'e', 'i', 'o', 'u'];
//if first letter = vowel, add 'way' to end of sentence
// else return all letters before first vowel and append to end (with 'ay')
for (var i = 0; i < str.length; i++) {
if (vowel.indexOf(str[0]) > -1) {
return str + 'way';
} else if(vowel.indexOf(str[i]) !== -1) {
return str.substr(i) + str.slice(0,i) + 'ay';
}
}
}
Note how I added the if to test if the character is a vowel.
jsfiddle

Related

Break Camel Case function in JavaScript

I have been attempting to solve this codewars problem for a while in JavaScript:
"Complete the solution so that the function will break up camel casing, using a space between words. Example:"
"camelCasing" => "camel Casing"
"identifier" => "identifier"
"" => ""
I have it almost all the way, but for some reason my code is selecting the wrong space to add a blank space.
I'm hoping someone can tell me what I am doing wrong.
function solution(string) {
let splitStr = string.split("");
let newStr = string.split("");
let capStr = string.toUpperCase().split("");
for (i = 0; i < splitStr.length; i++) {
if (splitStr[i] === capStr[i]) {
newStr.splice(i, 0, ' ');
}
}
return newStr.join("");
}
console.log('camelCasing: ', solution('camelCasing'));
console.log('camelCasingTest: ', solution('camelCasingTest'));
The first insertion into newStr will be at the correct spot, but after that insertion of the space, the letters that follow it in newStr will be at an increased index. This means that when the next capital is found at i in splitStr (which did not change), the insertion into newStr (which did change) should really be at i+1.
A solution is to make your loop iterate from end to start:
function solution(string) {
let splitStr = string.split("");
let newStr = string.split("");
let capStr = string.toUpperCase().split("");
for (i = splitStr.length - 1; i >= 0; i--) {
if (splitStr[i] === capStr[i]) {
newStr.splice(i, 0, ' ');
}
}
return newStr.join("");
}
console.log('camelCasing: ', solution('camelCasing'));
console.log('camelCasingTest: ', solution('camelCasingTest'));
This kind of problem is however much easier solved with a regular expression:
function solution(string) {
return string.replace(/[A-Z]/g, " $&");
}
console.log('camelCasing: ', solution('camelCasing'));
console.log('camelCasingTest: ', solution('camelCasingTest'));
Explanation of the regular expression:
[A-Z] a capital letter from the Latin alphabet.
$& backreference to the matched letter, used in the replacement.
g global flag so all matches are replaced.
Here could be a solution with a simple loop and some if conditions
const breakCamelCase = (word) => {
let result = "";
// loop on letter
for (let letter of word) {
// if letter is uppercase and not the first letter of the word add a space followed by the letter
if (letter == letter.toUpperCase() && result) {
result += ` ${letter}`;
} else { // else just add the letter
result += letter;
}
}
return result;
}
function solution(string) {
let splitStr = string.split("");
let newStr = "";
splitStr.forEach(e =>{
if(e === e.toUpperCase()) newStr +=" "+e;
else newStr += e;
});
return newStr;
}
console.log(solution('camelCasing'));//success = "camel Casing"
console.log(solution('camelCasingTest'));

checking the same condition for all elements in array javascript

I'm trying to code a basic hangman game. When the user guesses correctly the word then the word is uploaded to an "answer" array and displayed to the user , when the guessed word is wrong then a warning should say "try again" and the input value cleared.
The thing is even when one word is actually guessed correctly there's still all the other words that were not so I end up getting the same warning "try again"
So I think I need to loop the original word and check to see if none of the elements are equal to the letter guess and for that I'm using every() but I can't make it work and "try again" always shows...
Help please
function generate(){
pickedWord = words[Math.floor(Math.random() * words.length)];
console.log(pickedWord)
for(let i = 0; i<pickedWord.length; i++){
word[i] = "_";
}
wordGuess.textContent = word.join(" ");
}
function getInput(e){
e.preventDefault();
let guess = input.value.toLowerCase();
if(guess.length > 1){
alert("type just one letter")
input.value = ""
}
else{
for(let i=0; i < pickedWord.length; i++){
if(guess === pickedWord[i]){
word[i] = guess;
wordGuess.textContent = word.join(" ");
input.value="";
}
else {
const letter = [pickedWord[i]]
console.log(letter)
const itemGuessed = letter.every(el => el !== guess)
if(itemGuessed){
alerta.textContent = "try again"
input.value="";
}
}
}
}
}
```
You actually didn't specify what does the words array look like, so I'm gonna assume tht it's an array of strings. Something like
const words = ['applejuice', 'bananashake', 'peanutbutter'];
So first of all, I actually don't understand what is the purpose of const letter = [pickedWord[i]]. Say the picked word was 'apple', and i was 0, then letter will be equal to ['a'], which makes the line const itemGuessed = letter.every(el => el !== guess) completely meaningless.
I also think it's better to check if guess is included in the pickedWord outside of the loop, using either pickedWord.every(el => el !== guess) or pickedWord.includes(guess) (though I prefer the latter!).
Anyway, I had a little rewrite on your code:
let pickedWord;
const words = ['applejuice', 'bananashake', 'peanutbutter'];
let word = [];
function generate() {
pickedWord = words[Math.floor(Math.random() * words.length)];
word = Array(pickedWord.length).fill('_');
console.log(pickedWord, word.join(''));
}
let guessedLetters = [];
function getInput(input){
// e.preventDefault();
const guess = input.toLowerCase().replace(/\s/g, '');
if(guess.length !== 1){
alert("type one letter");
}else{
if (pickedWord.includes(guess) === -1) {
alert("letter not in word");
}else if(guessedLetters.includes(guess)) {
alert("that letter is already guessed");
}else{
guessedLetters.push(guess)
for (let i = 0; i < pickedWord.length; i++) {
if(guess === pickedWord[i]){
word[i] = guess;
}
}
}
}
}
generate();
//cases where 1: same letter guessed twice
// 2: more than 1 letters guessed at once
// 3: capital letters guessed
// 4: empty string / space guessed
for (let input of ['', ' ', 'a', 'a', 'B', 'c', 'Cc', 'd', 'E', 'f', 'g', 'h']){
getInput(input);
console.log(word.join(''));
}
Note that I removed input.value=""; line for the demonstration purposes.
Please feel free to ask anything if you had a problem with my code. cheers!

FCC Intermediate Algorithm Scripting: Pig Latin

This test objective is to take 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.
My main issue is to iterate through the string until it reaches a vowel and put the first consonants letters to the end of the string.
I’m having trouble iterating through the string until it reaches a vowel. How do you iterate a string until it stops at the first vowel? How do you get all of the first consonant letters before it reaches vowel? I iterate the string by using the for loop, and I use the “if” statement if the first letters are consonant.
function translatePigLatin(str) {
var vowel = /[aeiou]/g;
var cons = /[^aeiou]/g;
console.log(cons.test(str[2]))
var consonants = [];
var index = str.charAt(0);
console.log(str.slice(1, str.length))
for(var i = 0; i < str.length; i++){
console.log(str[i])
if(cons.test(str[i])){
consonants.push(str.charAt(i));
console.log(consonants)
var slice = str.slice(consonants.length, str.length);
}
}
return consonants + 'ay';
}
translatePigLatin("glove");
I would focus on just finding the index of the first vowel. Then you can test whether that index is 0 or something else. If it's zero, just add the way otherwise slice on that index:
function translatePigLatin(str) {
const vowels = ['a', 'e', 'i', 'o', 'u'];
let ind = [...str.toLowerCase()].findIndex(s => vowels.includes(s))
return ind
? str.slice(ind) + str.slice(0, ind) + 'ay' // doesn't start with vowel
: str + 'way'
}
console.log(translatePigLatin('glove'))
console.log(translatePigLatin('apple'))
console.log(translatePigLatin('Mark'))
console.log(translatePigLatin('Javascript'))
I'm not sure what the pig latin rules are for the edge case of a word with no vowels like rhythm.
I think you should break the problem into some basic cases, like I did in the code below:
Check if the first letter is a vowel; if true, just add 'way' to the end of the word and break the loop
If the current letter is a consonant (that means the first condition is not true), we just continue iterating
If the current letter is a vowel, we split the word into two separate parts and we add them on the other way around, not forgetting to ad the 'ay' suffix.
In the code below I also added to the vowels array the uppercase versions. With some modifications, it can be made to jump over delimiters. The Pig Latin rules were those I found on Wikipedia (although I did not find any rules for words only with consonants, so I put them in the first case).
Cheers!
function has(a, e) {
return a.indexOf(e) > -1;
}
function translateWord(str) {
let vows = ['a', 'e', 'i', 'o', 'u'];
vows = vows.concat(vows.map(v => v.toUpperCase()));
let lastVowelIndex = 0;
let conv = '';
for (let i = 0; i < str.length; ++i) {
let currentChar = str[i];
/* If the first character is a voewl, we just
* add the 'way' suffix to the initial word.
* I applied the same rule for words without
* consonants.
*/
if ((i === 0 && has(vows, currentChar))
|| (i === str.length - 1)) {
conv = str + 'way';
break;
}
/* If the current character is a consonant, we
* just continue until we reach a vowel.
*/
if (!has(vows, currentChar))
continue;
/* At this point, we reached a vowel, so we do the
* appropriate transformations.
*/
let firstPart = str.slice(0, i);
let secondPart = str.slice(i);
conv = secondPart + firstPart + 'ay';
break;
}
return conv;
}
function translateToPigLatin(str) {
let words = str.split(' ');
let converted = words.map(w => translateWord(w));
return converted.join(' ');
}
let s = translateToPigLatin("I have no rythm");
console.log(s);
Why not use a RegExp?
function translatePigLatin(str) {
let res = '';
let regex = /[aeiou]/;
if (!regex.test(str)) {
res = str + 'ay';
} else if (regex.test(str[0])) {
res = str + 'way';
} else {
let x = str.indexOf(regex.exec(str)[0]);
res = str.substr(x) + str.substr(0, x) + 'ay'
}
return res;
}

How can I use a switch statement to create a Piglatin translator? [duplicate]

So for my cit class I have to write a pig Latin converter program and I'm really confused on how to use arrays and strings together.
The rules for the conversion are simple, you just move the first letter of the word to the back and then add ay. ex: hell in English would be ellhay in pig Latin
I have this so far:
<form name="form">
<p>English word/sentence:</p> <input type="text" id="english" required="required" size="80" /> <br />
<input type="button" value="Translate!" onClick="translation()" />
<p>Pig Latin translation:</p> <textarea name="piglat" rows="10" cols="60"></textarea>
</form>
<script type="text/javascript">
<!--
fucntion translation() {
var delimiter = " ";
input = document.form.english.value;
tokens = input.split(delimiter);
output = [];
len = tokens.length;
i;
for (i = 1; i<len; i++){
output.push(input[i]);
}
output.push(tokens[0]);
output = output.join(delimiter);
}
//-->
</script>
I'd really appreciate any help I can get!
function translate(str) {
str=str.toLowerCase();
var n =str.search(/[aeiuo]/);
switch (n){
case 0: str = str+"way"; break;
case -1: str = str+"ay"; break;
default :
//str= str.substr(n)+str.substr(0,n)+"ay";
str=str.replace(/([^aeiou]*)([aeiou])(\w+)/, "$2$3$1ay");
break;
}
return str;
}
translate("paragraphs")
I think the two things you really need to be looking at are the substring() method and string concatentation (adding two strings together) in general. Being that all of the objects in the array returned from your call to split() are strings, simple string concatentation works fine. For example, using these two methods, you could move the first letter of a string to the end with something like this:
var myString = "apple";
var newString = mystring.substring(1) + mystring.substring(0,1);
This code is basic, but it works. First, take care of the words that start with vowels. Otherwise, for words that start with one or more consonants, determine the number of consonants and move them to the end.
function translate(str) {
str=str.toLowerCase();
// for words that start with a vowel:
if (["a", "e", "i", "o", "u"].indexOf(str[0]) > -1) {
return str=str+"way";
}
// for words that start with one or more consonants
else {
//check for multiple consonants
for (var i = 0; i<str.length; i++){
if (["a", "e", "i", "o", "u"].indexOf(str[i]) > -1){
var firstcons = str.slice(0, i);
var middle = str.slice(i, str.length);
str = middle+firstcons+"ay";
break;}
}
return str;}
}
translate("school");
If you're struggling with arrays this might be a bit complicated, but it's concise and compact:
var toPigLatin = function(str) {
return str.replace(/(^\w)(.+)/, '$2$1ay');
};
Demo: http://jsfiddle.net/elclanrs/2ERmg/
Slightly improved version to use with whole sentences:
var toPigLatin = function(str){
return str.replace(/\b(\w)(\w+)\b/g, '$2$1ay');
};
Here's my solution
function translatePigLatin(str) {
var newStr = str;
// if string starts with vowel make 'way' adjustment
if (newStr.slice(0,1).match(/[aeiouAEIOU]/)) {
newStr = newStr + "way";
}
// else, iterate through first consonents to find end of cluster
// move consonant cluster to end, and add 'ay' adjustment
else {
var moveLetters = "";
while (newStr.slice(0,1).match(/[^aeiouAEIOU]/)) {
moveLetters += newStr.slice(0,1);
newStr = newStr.slice(1, newStr.length);
}
newStr = newStr + moveLetters + "ay";
}
return newStr;
}
Another way of doing it, using a separate function as a true or false switch.
function translatePigLatin(str) {
// returns true only if the first letter in str is a vowel
function isVowelFirstLetter() {
var vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
for (i = 0; i < vowels.length; i++) {
if (vowels[i] === str[0]) {
return true;
}
}
return false;
}
// if str begins with vowel case
if (isVowelFirstLetter()) {
str += 'way';
}
else {
// consonants to move to the end of string
var consonants = '';
while (isVowelFirstLetter() === false) {
consonants += str.slice(0,1);
// remove consonant from str beginning
str = str.slice(1);
}
str += consonants + 'ay';
}
return str;
}
translatePigLatin("jstest");
this is my solution code :
function translatePigLatin(str) {
var vowel;
var consonant;
var n =str.charAt(0);
vowel=n.match(/[aeiou]/g);
if(vowel===null)
{
consonant= str.slice(1)+str.charAt(0)+”ay”;
}
else
{
consonant= str.slice(0)+”way”;
}
var regex = /[aeiou]/gi;
var vowelIndice = str.indexOf(str.match(regex)[0]);
if (vowelIndice>=2)
{
consonant = str.substr(vowelIndice) + str.substr(0, vowelIndice) + ‘ay’;
}
return consonant;
}
translatePigLatin(“gloove”);
Yet another way.
String.prototype.toPigLatin = function()
{
var str = "";
this.toString().split(' ').forEach(function(word)
{
str += (toPigLatin(word) + ' ').toString();
});
return str.slice(0, -1);
};
function toPigLatin(word)
{
//Does the word already start with a vowel?
if(word.charAt(0).match(/a*e*i*o*u*A*E*I*O*U*/g)[0])
{
return word;
}
//Match Anything before the firt vowel.
var front = word.match(/^(?:[^a?e?i?o?u?A?E?I?O?U?])+/g);
return (word.replace(front, "") + front + (word.match(/[a-z]+/g) ? 'a' : '')).toString();
}
Another way of Pig Latin:
function translatePigLatin(str) {
let vowels = /[aeiou]/g;
var n = str.search(vowels); //will find the index of vowels
switch (n){
case 0:
str = str+"way";
break;
case -1:
str = str+"ay";
break;
default:
str = str.slice(n)+str.slice(0,n)+"ay";
break;
}
return str;
}
console.log(translatePigLatin("rhythm"));
Your friends are the string function .split, and the array functions .join and .slice and .concat.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array#Accessor_methods
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String#Methods_unrelated_to_HTML
warning: Below is a complete solution you can refer to once you have finished or spent too much time.
function letters(word) {
return word.split('')
}
function pigLatinizeWord(word) {
var chars = letters(word);
return chars.slice(1).join('') + chars[0] + 'ay';
}
function pigLatinizeSentence(sentence) {
return sentence.replace(/\w+/g, pigLatinizeWord)
}
Demo:
> pigLatinizeSentence('This, is a test!')
"hisTay, siay aay esttay!"

Pig Latin Translator - JavaScript

So for my cit class I have to write a pig Latin converter program and I'm really confused on how to use arrays and strings together.
The rules for the conversion are simple, you just move the first letter of the word to the back and then add ay. ex: hell in English would be ellhay in pig Latin
I have this so far:
<form name="form">
<p>English word/sentence:</p> <input type="text" id="english" required="required" size="80" /> <br />
<input type="button" value="Translate!" onClick="translation()" />
<p>Pig Latin translation:</p> <textarea name="piglat" rows="10" cols="60"></textarea>
</form>
<script type="text/javascript">
<!--
fucntion translation() {
var delimiter = " ";
input = document.form.english.value;
tokens = input.split(delimiter);
output = [];
len = tokens.length;
i;
for (i = 1; i<len; i++){
output.push(input[i]);
}
output.push(tokens[0]);
output = output.join(delimiter);
}
//-->
</script>
I'd really appreciate any help I can get!
function translate(str) {
str=str.toLowerCase();
var n =str.search(/[aeiuo]/);
switch (n){
case 0: str = str+"way"; break;
case -1: str = str+"ay"; break;
default :
//str= str.substr(n)+str.substr(0,n)+"ay";
str=str.replace(/([^aeiou]*)([aeiou])(\w+)/, "$2$3$1ay");
break;
}
return str;
}
translate("paragraphs")
I think the two things you really need to be looking at are the substring() method and string concatentation (adding two strings together) in general. Being that all of the objects in the array returned from your call to split() are strings, simple string concatentation works fine. For example, using these two methods, you could move the first letter of a string to the end with something like this:
var myString = "apple";
var newString = mystring.substring(1) + mystring.substring(0,1);
This code is basic, but it works. First, take care of the words that start with vowels. Otherwise, for words that start with one or more consonants, determine the number of consonants and move them to the end.
function translate(str) {
str=str.toLowerCase();
// for words that start with a vowel:
if (["a", "e", "i", "o", "u"].indexOf(str[0]) > -1) {
return str=str+"way";
}
// for words that start with one or more consonants
else {
//check for multiple consonants
for (var i = 0; i<str.length; i++){
if (["a", "e", "i", "o", "u"].indexOf(str[i]) > -1){
var firstcons = str.slice(0, i);
var middle = str.slice(i, str.length);
str = middle+firstcons+"ay";
break;}
}
return str;}
}
translate("school");
If you're struggling with arrays this might be a bit complicated, but it's concise and compact:
var toPigLatin = function(str) {
return str.replace(/(^\w)(.+)/, '$2$1ay');
};
Demo: http://jsfiddle.net/elclanrs/2ERmg/
Slightly improved version to use with whole sentences:
var toPigLatin = function(str){
return str.replace(/\b(\w)(\w+)\b/g, '$2$1ay');
};
Here's my solution
function translatePigLatin(str) {
var newStr = str;
// if string starts with vowel make 'way' adjustment
if (newStr.slice(0,1).match(/[aeiouAEIOU]/)) {
newStr = newStr + "way";
}
// else, iterate through first consonents to find end of cluster
// move consonant cluster to end, and add 'ay' adjustment
else {
var moveLetters = "";
while (newStr.slice(0,1).match(/[^aeiouAEIOU]/)) {
moveLetters += newStr.slice(0,1);
newStr = newStr.slice(1, newStr.length);
}
newStr = newStr + moveLetters + "ay";
}
return newStr;
}
Another way of doing it, using a separate function as a true or false switch.
function translatePigLatin(str) {
// returns true only if the first letter in str is a vowel
function isVowelFirstLetter() {
var vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
for (i = 0; i < vowels.length; i++) {
if (vowels[i] === str[0]) {
return true;
}
}
return false;
}
// if str begins with vowel case
if (isVowelFirstLetter()) {
str += 'way';
}
else {
// consonants to move to the end of string
var consonants = '';
while (isVowelFirstLetter() === false) {
consonants += str.slice(0,1);
// remove consonant from str beginning
str = str.slice(1);
}
str += consonants + 'ay';
}
return str;
}
translatePigLatin("jstest");
this is my solution code :
function translatePigLatin(str) {
var vowel;
var consonant;
var n =str.charAt(0);
vowel=n.match(/[aeiou]/g);
if(vowel===null)
{
consonant= str.slice(1)+str.charAt(0)+”ay”;
}
else
{
consonant= str.slice(0)+”way”;
}
var regex = /[aeiou]/gi;
var vowelIndice = str.indexOf(str.match(regex)[0]);
if (vowelIndice>=2)
{
consonant = str.substr(vowelIndice) + str.substr(0, vowelIndice) + ‘ay’;
}
return consonant;
}
translatePigLatin(“gloove”);
Yet another way.
String.prototype.toPigLatin = function()
{
var str = "";
this.toString().split(' ').forEach(function(word)
{
str += (toPigLatin(word) + ' ').toString();
});
return str.slice(0, -1);
};
function toPigLatin(word)
{
//Does the word already start with a vowel?
if(word.charAt(0).match(/a*e*i*o*u*A*E*I*O*U*/g)[0])
{
return word;
}
//Match Anything before the firt vowel.
var front = word.match(/^(?:[^a?e?i?o?u?A?E?I?O?U?])+/g);
return (word.replace(front, "") + front + (word.match(/[a-z]+/g) ? 'a' : '')).toString();
}
Another way of Pig Latin:
function translatePigLatin(str) {
let vowels = /[aeiou]/g;
var n = str.search(vowels); //will find the index of vowels
switch (n){
case 0:
str = str+"way";
break;
case -1:
str = str+"ay";
break;
default:
str = str.slice(n)+str.slice(0,n)+"ay";
break;
}
return str;
}
console.log(translatePigLatin("rhythm"));
Your friends are the string function .split, and the array functions .join and .slice and .concat.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array#Accessor_methods
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String#Methods_unrelated_to_HTML
warning: Below is a complete solution you can refer to once you have finished or spent too much time.
function letters(word) {
return word.split('')
}
function pigLatinizeWord(word) {
var chars = letters(word);
return chars.slice(1).join('') + chars[0] + 'ay';
}
function pigLatinizeSentence(sentence) {
return sentence.replace(/\w+/g, pigLatinizeWord)
}
Demo:
> pigLatinizeSentence('This, is a test!')
"hisTay, siay aay esttay!"

Categories