How can I exclude punctuation in "pig latin" function? - javascript

I apologize if this question has been answered somewhere - please point me in the right direction if so. I have read through a bunch of solutions and have not yet cracked it!
Sooo...basically, I need to:
Move the first letter of each word to the end of it, then add "ay" to the end of the word. Leave punctuation marks untouched.
This is my code so far:
function pigIt(str) {
var newStr = str.split(" ");
var changed = newStr.map(function(input) {
return input.substring(1) + input.charAt(0) + "ay";
});
changed = changed.join(" ");
return changed;
}
console.log(pigIt('Pig latin is cool'));
As you can see, the code will work for any input that doesn't include punctuation. Great. Now I need to maybe add a Regex somewhere to exclude punctuation but I don't know where to put it! Please help!!

You could split by the word boundary /(\W+)/ while capturing separator. Transform words only. And then join back.
function pigIt(str) {
var newStr = str.split(/(\W+)/); // ['Pig', ' ', 'latin', ',- ',..]
var changed = newStr.map(function(input) {
if (!/\w/.test(input)) return input // keep non word elements as is
return input.substring(1) + input.charAt(0) + "ay";
});
return changed.join("");
}
console.log(pigIt('Pig latin,- is cool!'));

I think because you are going to want to put the punctuation back in the same place after processing, then you will probably be better of doing it all manually.
Loop the input 1 char at a time and build a 'word buffer', every time you hit a non-letter character then process the word buffer and append the non-letter character too.
function pigIt(str) {
var process = function(s) {
if (s.length < 2) {
return s;
}
return s.substring(1) + s.charAt(0) + "ay";
};
var result = '';
var buffer = '';
for (var i = 0; i < str.length; i++) {
var c = str[i];
if (c.match(/[a-zA-Z]/i)) {
buffer += c;
} else {
if (buffer.length) {
result += process(buffer);
buffer = '';
}
result += c;
}
}
result += process(buffer);
buffer = '';
return result;
}
var output = pigIt('Pig latin is cool.');
console.log(output);

Related

Alternate adding a character to the beginning and end of string

I am trying to solve a Javascript puzzle. I need to write a function that uses a while loop to add a character to the beginning of string and then on the next loop adds the character to the end of the string and to the beginning on the loop after that. The function takes two parameters a string and a number of characters to add.
So far I have
function padIt(str,n){
//coding here
var newStr = "";
var padding = "*";
var i = 0;
while(i<=n){
if (i%2===0){
newStr = newStr+padding;
} else{
newStr = padding+str;
}
i++;
}
return newStr;
}
I am passing the first two test cases but it won't work properly for the third time through the loop. Expecting "* * a *" for n = 3 but only getting "*a". It has to be a while loop so I don't know if I am not setting the loop up correctly or if I am messing up the variables. Any help is greatly appreciated as I am totally lost.
You can do it by writing code like below,
function padIt(str,n, pad = "*"){
var left = Math.ceil(n/2), right = n - left;
return pad.repeat(left) + str + pad.repeat(right);
}
And this function would print,
console.log("a", 1); // "*a"
console.log("a", 2); // "*a*"
console.log("a", 10); // "*****a*****"
Thing need to be read after implementing this code,
String.prototype.repeat()
You need to comment your newStr+=padding; line.
Here is the refined code,
function padIt(str,n){
//coding here
var newStr = "";
var padding = "*";
var i = 0;
while(i<=n){
i++;
newStr=padding+str;
//newStr+=padding;
}
return newStr;
}
HTH
function padIt(str,n){
while(n>0){
if(n%2 === 0){
str = str + '*';
} else{
str = '*' + str;
}
n--;
}
return str;
}

Javascript Return the location of the first letter of each word in a string using a loop

Having trouble coming up with code doing this.
So for example here is my string.
var str = "Hello how are you today?";
How would I manipulate this string to return the position of the first letter of each word using a loop?
this will give you the result with less complicated code and a single loop
function foo(str) {
var pos = [];
var words = str.split(' ');
pos.push(1);
var prevWordPos;
for (var i = 1; i < words.length; i++) {
prevWordPos = pos[i - 1] + words[i - 1].length;
pos.push((str.indexOf(words[i], prevWordPos) + 1));
}
return pos;
}
You should search for a question before asking it in case it's already been asked and answered.
Get first letter of each word in a string, in Javascript
You can use a regexp replace passing a function instead of a replacement string, this will call the function for each match:
str.replace(/[^ ]+/g, function(match, pos) {
console.log("Word " + match + " starts at position " + pos);
});
The regexp meaning is:
[^ ]: anything excluding space
+: one or more times
"g" option: not only first match, but each of them
in other words the function will be called with sequences of non-spaces. Of course you can define what you consider a "word" differently.
Here is a Solution with two Loops, i hope that is close enough ;)
var starts = [];
var str = "How are you doing today?";
//var count = 0;
var orgStr = str;
while (str.indexOf(" ") > 0) {
if (starts.length > 0) {
starts.push(starts[starts.length - 1] + str.indexOf(" ") +1);
} else {
starts.push(1);
starts.push(str.indexOf(" ") +2);
//alert(str);
}
str = str.substring(str.indexOf(" ") + 1);
}
for (var i = 0; i < starts.length; i++) {
alert(starts[i] + ": " + orgStr.substring(starts[i]-1,starts[i]))
}
Easiest would be to search a regular expression \b\w and collect match.start() match.index for each match. Loop while there's matches.
EDIT: wrong language. lol.

Need to chunk strings into 140-character chunks while respecting words

I have a very simple problem but need a solution that works. I have a node script that opens a text file, loops over each line and chunks the line if its over 140 characters but needs to respect word boundaries. This is what I have so far but the lines come out unaffected. I've also tried _.invoke(lines, function() { splitText(this); }; but this also leaves the lines unaffected. Can anyone suggest another way of doing this?
var args = process.argv.splice(2),
fs = require('fs'),
_ = require('underscore'),
splitText;
splitText = function (textSegment) {
var len = 140, curr = len, prev = 0, output = [], currReverse;
while (textSegment[curr]) {
if (textSegment[curr++] == ' ') {
output.push(textSegment.substring(prev, curr));
prev = curr;
curr += len;
} else {
currReverse = curr;
do {
if (textSegment.substring(currReverse - 1, currReverse) == ' ') {
output.push(textSegment.substring(prev, currReverse));
prev = currReverse;
curr = currReverse + len;
break;
}
currReverse--;
} while (currReverse > prev);
}
}
output.push(textSegment.substring(prev));
return output;
}
text = fs.readFileSync(args[0], 'utf-8');
lines = text.split("\n");
lines = _.filter(lines, function (line) {
return line.length >= 100;
});
lines = _.map(lines, function (line) {
return splitText(line);
});
fs.writeFile(args[0], lines.join("\n"), function (err) {
if (err) throw err;
console.log('test');
});
I don't have any experience with underscore.js, but I do know a fairly straightforward way to fix this without it:
function formatStr(text, len) {
len = len||140;
var i=0,
str, newline, breakpt,
formatted = '';
while (i+len<text.length) {
str = text.substr(i, len);
newline = str.indexOf('\n');
if (newline!=-1) {
formatted += str.substr(0,newline+1);
console.log(i,newline);
i += newline + 1;
continue;
}
breakpt = str.lastIndexOf(' ');
formatted += str.substr(0,breakpt) + '\n';
i+=breakpt+1;
}
// add last line to the end and return; credit to Charly
// for mentioning this was missing.
return formatted + text.substr(i);
}
DEMO
What this loop does is the following:
Store the next 140 characters in a var
test if there are already any newlines in this string
if so, just add that part of the string to the formatted string, and continue from there
get the last index of a space in the string variable
append the part of the string until the next space in the formatted string
finally, return the formatted string.
Kind of an old thread but here's a quick solution.
Try this regex, you can see how it works here: http://regexper.com/#%5E(%5Cr%5Cn%7C.)%7B1%2C140%7D%5Cb
str.match(/^(\r\n|.){1,140}\b/g).join('')

Replace letters in string with the next letter, and capitalize vowels in the changed string

function LetterChanges(str) {
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (var i = 0; i < str.length; i++) {
var index = alphabet.indexOf(str[i])
if (/[a-zA-Z]/.test(str[i])) {
str = str.replace(str[i], alphabet.charAt(index + 1));
}
if (/[aeiou]/.test(str[i])) {
str = str.replace(str[i], alphabet.charAt(index + 26));
}
}
return str;
}
When I call LetterChanges("hello"), it returns 'Ifmmp' which is correct, but when "sent" is passed it returns 'ufOt' instead of 'tfOu'. Why is that?
str.replace() replaces the first occurrence of the match in the string with the replacement. LetterChanges("sent") does the following:
i = 0 : str.replace("s", "t"), now str = "tent"
i = 1 : str.replace("e", "f"), now str = "tfnt"
i = 2 : str.replace("n", "o"), now str = "tfot", then
str.replace("o", "O"), now str = "tfOt"
i = 3 : str.replace("t", "u"), now str = "ufOt"
return str
There are several issues. The main one is that you could inadvertently change the same letter several times.
Let's see what happens to the s in sent. You first change it to t. However, when it comes to changing the final letter, which is also t, you change the first letter again, this time from t to u.
Another, smaller, issue is the handling of the letter z.
Finally, your indexing in the second if is off by one: d becomes D and not E.
You can use String.replace to avoid that:
function LetterChanges(str) {
return str.replace(/[a-zA-Z]/g, function(c){
return String.fromCharCode(c.charCodeAt(0)+1);
}).replace(/[aeiou]/g, function(c){
return c.toUpperCase();
});
}
But there is still a bug: LetterChanges('Zebra') will return '[fcsb'. I assume that is not your intention. You will have to handle the shift.
Try this one:
function LetterChanges(str) {
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var result = '';
var temp;
for (var i = 0; i < str.length; i++) {
var index = alphabet.indexOf(str[i])
if (/[a-zA-Z]/.test(str[i])) {
//str = str.replace(str[i], alphabet.charAt(index + 1));
temp= alphabet.charAt(index + 1);
index = index+1;
}
else if(str[i] == ' '){
temp = ' ';
}
if (/[aeiou]/.test(temp)) {
temp = alphabet.charAt(index + 26);
}
result += temp;
}
return result;
}
var str = 'bcd12';
str = str.replace(/[a-z]/gi, function(char) { //call replace method
char = String.fromCharCode(char.charCodeAt(0)+1);//increment ascii code of char variable by 1 .FromCharCode() method will convert Unicode values into character
if (char=='{' || char=='[') char = 'a'; //if char values goes to "[" or"{" on incrementing by one as "[ ascii value is 91 just after Z" and "{ ascii value is 123 just after "z" so assign "a" to char variable..
if (/[aeiuo]/.test(char)) char = char.toUpperCase();//convert vowels to uppercase
return char;
});
console.log(str);
Check this code sample. There is no bug in it. Not pretty straight forward but Works like a charm. Cheers!
function LetterChanges(str) {
var temp = str;
var tempArr = temp.split("");//Split the input to convert it to an Array
tempArr.forEach(changeLetter);/*Not many use this but this is the referred way of using loops in javascript*/
str = tempArr.join("");
// code goes here
return str;
}
function changeLetter(ele,index,arr) {
var lowerLetters ="abcdefghijklmnopqrstuvwxyza";
var upperLetters ="ABCDEFGHIJKLMNOPQRSTUVWXYZA";
var lowLetterArr = lowerLetters.split("");
var upLetterArr = upperLetters.split("");
var i =0;
for(i;i<lowLetterArr.length;i++){
if(arr[index] === lowLetterArr[i]){
arr[index] = lowLetterArr[i+1];
arr[index]=arr[index].replace(/[aeiou]/g,arr[index].toUpperCase());
return false;
}
if(arr[index] === upLetterArr[i]){
arr[index] = upLetterArr[i+1];
arr[index]=arr[index].replace(/[aeiou]/g,arr[index].toUpperCase());
return false;
}
}
}
// keep this function call here
// to see how to enter arguments in JavaScript scroll down
LetterChanges(readline());

Split method and then concatenate

What I need to do is make this function to where it splits each part of the string entered, and then puts pig latin on each word, meaning it adds ay at the end of each word. Here's what I have so far:
function pigLatin(whatWeTitle) {
var alertThis = " ";
var splitArray = whatWeTitle.split(" ");
for ( i = 0; i < splitArray.length; i++) {
alertThis = makeSentenceCase(splitArray[i]) + " ";
var newWord3 = splitArray.substring(1, whatWeTitle.length) + newWord + 'ay';
alert(newWord3);
}
}
Right now, it just takes the first letter of the string and adds it to the end. It doesn't change each word to pig latin, just the whole phrase. I was wondering of anyone could help me with this. THanks.
You need to use [i] to get items of your array :
var word = splitArray[i];
var newWord3 = word.substring(1,word.length) + word[0] + 'ay';
The best, if you want to end up with the whole new sentence, is to change each word an join them at the end :
var splitArray = whatWeTitle.split(" ");
for ( i = 0; i < splitArray.length; i++) {
var word = splitArray[i];
splitArray[i] = word.substring(1,word.length) + word[0] + 'ay';
}
var newSentence = splitArray.join(' ');
alert(newSentence);
If you test a little, you'll see this algorithm doesn't like the dots or comma in your sentence. If you want something stronger, you'd need a regular expression, for example like this :
var newSentence = whatWeTitle.replace(/[^\. ,]+/g, function(word){
return word.slice(1) + word[0] + 'ay';
});
alert(newSentence);
This works by replacing in place the words in the text, using a function to transform each word.
Something like this ?
function pigLatin(whatWeTitle) {
var alertThis = " ";
var splitArray = whatWeTitle.split(" ");
var finalString = "";
for ( i = 0; i < splitArray.length; i++) {
finalString += splitArray[i]+ "ay ";
}
alert(finalString);
}
pigLatin("this is a test");
You probably want to split off the first consonant values and then append them along with 'ay'.
I would use a regex to accomplish this. Here is a JSFiddle showing an example.
First part is split the word
var words = text.split(" ");
Next part is to piglatinify™ each word
words = words.map(function(word){ return pigLatinifyWord(word);});
This is the piglatinify™ function
function pigLatinifyWord(word){
var result;
var specialMatches = word.match(/(\W|\D)+$/);
var specialChars;
if(specialMatches && specialMatches.length >= 0){
var specialIndex = word.indexOf(specialMatches[0]);
specialChars = word.slice(specialIndex);
word = word.substr(0, specialIndex);
}
var i = word.search(/^[^aeiou]/);
if(i >= 0){
result = word.slice(i+1) + word.slice(0, i+1) + "ay";
}
else{
result = word + "ay";
}
if(specialChars){
result += specialChars;
}
return result;
}
Update
JSFiddle example now includes handling for non-word non-digit characters

Categories