Palindrome Program avoiding spaces, punctuation in Javascript - javascript

I'm trying to make a palindrome program using javascript that will show if a string is palindrome or not by TRUE or FALSE even if the string has punctuation and spaces(ex- madam, i'm adam). But everytime I put a string I only get TRUE no matter what the string is. Here is my code,
function isPalindrome (str) {
var nopunctuation = str.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,"");
var nospaces = nopunctuation.replace(/\s/g,"");
var finalstring = nospaces;
var len = finalstring.length;
for ( var i = 0; i < Math.floor(finalstring/2); i++ ) {
if (finalstring[i] !== finalstring[len - 1 - i]) {
return false;
}
}
return true;
}
console.log(isPalindrome("madam i'm adam"));
Is there anything wrong with my code? Point to be noted, I'm not allowed to use any built-in or library function. Your help would be much appreciable. Tnx.

Within the "for" clause, replace "Math.floor(finalstring/2)" by "Math.floor(len/2)"
Also, you might want to improve your punctuation removal so that it also removes apostrophes, for instance.
So your code would become the following:
function isPalindrome (str) {
var nopunctuation = str.replace(/\W/g,"");
var nospaces = nopunctuation.replace(/\s/g,"");
var finalstring = nospaces;
var len = finalstring.length;
for ( var i = 0; i < Math.floor(len/2); i++ ) {
if (finalstring[i] !== finalstring[len - 1 - i]) {
return false;
}
}
return true;
}

Related

Format string and deleting special characters using ASCII code doesn't work (JavaScript)

Im trying to format any given string using ASCII code for reference. The format must delete any special character except numbers, "-" or "_" and spaces. Here's the code:
function FormatString(sentence) {
result = new String();
j = 0;
sentence = sentence.toUpperCase();
i = 0;
while(i < sentence.length) {
if (
(sentence[i]>=65 && sentence[i]<=90) ||
(sentence[i]>=48 && sentence[j]<=57) ||
sentence[i]==32 || sentence[i]==45
) {
sentence[j] = result[i];
j = j + 1;
}
i = i + 1;
}
return result;
}
and then call the function
console.log(FormatString('No running in the hallways!!!'))
the output should be "No running in the hallways"
Provided that using Regular Expressions would be the best way to solve your problem, I am assuming you want to use ASCII comparison for a reason.
The following solution works:
function FormatString (sentence) {
let result = "";
const uppercaseSentence = sentence.toUpperCase();
for (let i=0; i<uppercaseSentence.length; i++) {
let cc = uppercaseSentence.charCodeAt(i);
if ((cc>=65 && cc<=90) || (cc>=48 && cc<=57) || cc==32 || cc==45) {
result += sentence[i];
}
}
return result;
}
I am reporting below your function and commenting what was wrong with it:
function FormatString(sentence) {
// you are declaring a global variable here.
// let result = ... or var result = ... makes it local
// In javascript you can use an string literal `""` in place of new String()
result = new String();
// again a global variable
j = 0;
// you are chaning the passed parameter to an uppercase string
// you lost the original string now
sentence = sentence.toUpperCase();
// again a global variable
i = 0;
// nothing wron with the while loop, only the for loop is more concise in
// this case
while(i < sentence.length) {
if (
// sentence[i] is a streing with length 1 and it returns false if
// compared with a number. Use instead sentence.charCodeAt(i) which
// returns the ASCII code of the i-th character
(sentence[i]>=65 && sentence[i]<=90) ||
// there is a j here in place of an i
(sentence[i]>=48 && sentence[j]<=57) ||
sentence[i]==32 || sentence[i]==45
) {
// you can't assign single characters in javascript
// what you want to do is result += sentence[i],
// but remember that sentence is now all uppercase and so will be
// result!
sentence[j] = result[i];
j = j + 1;
}
i = i + 1;
}
return result;
}
Maybe string.replace with regex will help in your need:
const regex = /[-_]/g
"afasf-afsaf_fafa".replace(regex,''); //"afasfafsaffafa"

Palindrome Checker need a hand

I'm working on freeCodeCamp's Palindrome Checker. My code is a bit messy but it pretty works on every test except the nineth one. palindrome("almostomla") should return false but in my code it returns trueinstead. I think my nineth code has a little problem but couldn't solve that. I wonder where am I missing something.
function palindrome(str) {
let str1 = str.replace(/[^a-zA-Z\d:]/gi, '');
let str2 = str1.replace(/,/gi, '');
let str3 = str2.replace(/\./gi, '');
let str4 = str3.replace(/_/, "-");
let myStr = str4.toLowerCase(); //My string is ready for play
for (let i = 0; i < myStr.length; i++) {
if (myStr[i] != myStr[myStr.length - (i+1)]) { //I think there is a little mistake on this line
return false;
} else {
return true;
}
}
The problem is that you're only checking the first and last characters of the string. You should return true only after all iterations have finished:
function palindrome(str) {
let str1 = str.replace(/[^a-zA-Z\d:]/gi, '');
let str2 = str1.replace(/,/gi, '');
let str3 = str2.replace(/\./gi, '');
let str4 = str3.replace(/_/, "-");
let myStr = str4.toLowerCase(); //My string is ready for play
for (let i = 0; i < myStr.length; i++) {
if (myStr[i] != myStr[myStr.length - (i + 1)]) {
return false;
}
}
return true;
}
console.log(palindrome("almostomla"));
console.log(palindrome("foof"));
console.log(palindrome("fobof"));
console.log(palindrome("fobbf"));
Note that your initial regular expression is sufficient - it removes all characters that aren't alphabetical, numeric, or :, so the other 3 regular expressions you run later are superfluous. Since you're using the i flag, you can also remove the A-Z from the regex:
const stringToTest = str.replace(/[^a-z\d:]/gi, '');
It would also probably be easier just to .reverse() the string:
function palindrome(str) {
const strToTest = str.replace(/[^a-z\d:]/gi, '');
return strToTest.split('').reverse().join('') === strToTest;
}
console.log(palindrome("almostomla"));
console.log(palindrome("foof"));
console.log(palindrome("fobof"));
console.log(palindrome("fobbf"));

Protecting Punctuation in Custom Uppercase-Conversion Function in JavaScript

function func1(word) {
matches = word.match(/([A-Z][a-z]+[-!$%^&*()_+|~=`{}\[\]:";'<>?,.\/]*)/g);
if (!matches || matches.length === 1) {
return word.toUpperCase(); }
else return func2(matches) }
function func2(matched) {
x = (matches.length) - 1;
matches[x] = matches[x].toUpperCase();
return matches.join('');
}
function func3(isolated) {
output = isolated.split(/\s/);
output2 = [];
for (i = 0; i < output.length; i++) {
output2.push(func1(output[i])); }
output = output2.join(' ');
return output;
}
The idea is to convert things to uppercase, rendering McGee, McIntosh, etc as McGEE, McINTOSH, etc. Resulted from this thread here: JavaScript Convert Names to Uppercase, Except Mc/Mac/etc
Initially it was destroying all punctuation, because it didn't fit in with the matches so it just vanished into thin air. So I added the punctuation into the regular expression on line two.
Unfortunately, I then came across the word "Free-Throw", which renders as "Free-THROW" instead of "FREE-THROW". Under the old code it rendered as "FreeTHROW", which isn't any better.
Is there a way I can tackle this other than carefully-phrased inputs? It's for an After Effects expression so there aren't any users to deal with but I'd rather be able to include that hyphen, and if a double-barreled McSomething shows up (McGee-Smith for example) I won't have much choice.
The comment suggesting limited scope is correct, just the wrong way around: rather than defining which prefixes to handle I can easily define punctuation to protect. Dashes and apostrophes are the only characters I really have to worry about appearing mid-word, and dashes are always going to be between "words" within a word.
So instead of all-capsing the last match to the regular expression, I now all-caps both that and any match which ends in a dash.
Apostrophes are removed before the process stars, and re-inserted at the same index after capitalisation is complete.
function func1(word) {
filter = word.indexOf("’");
word = word.replace("’","");
matches = word.match(/([-!$%^&*()_+|~=`{}\[\]:"“”;'’<>?,.\/]*[A-Z][a-z]+[-!$%^&*()_+|~=`{}\[\]:"“”;'’<>?,.\/]*)/g);
if (!matches || matches.length === 1) {
func2out = word.toUpperCase();
if (filter >= 0){
func2out = [func2out.slice(0,filter), "’", func2out.slice(filter)].join('');
}
return func2out;}
else return func2(matches) }
function func2(matched) {
for(x = 0; x < matches.length; x++) {
if (matches[x].indexOf('-') >= 0 || (x == (matches.length-1))) matches[x] = matches[x].toUpperCase(); }
func2out = matches.join('');
if (filter >= 0) {
func2out = [func2out.slice(0,filter), "’", func2out.slice(filter)].join('');
}
return func2out;
}
function func3(isolated) {
output = isolated.split(/\s/);
output2 = [];
for (i = 0; i < output.length; i++) {
output2.push(func1(output[i])); }
output = output2.join(' ');
return output;
}

More efficient palindrome code

This is a code I used for the coderbyte challenge "Palindrome". The challenge is to return true if str is the same foward and backward(a palindrome). I got all possible points but I know my code is a little ugly. What would be a more efficient way to write this code. It looks like I am repeating myself and it seems like something that could maybe be written with a for loop.I also see how it could return true when its really false if there was a longer palindrome without the use of a for loop:
function Palindrome(str) {
var low=str.toLowerCase()
var first = low.charAt(0);
var last = low.charAt(low.length-1);
var mid = low.charAt(1);
var mid1 = low.charAt(low.length-2);
if(first===last)
if(mid===mid1)
{
return true
}
else
{
return false
}
else
{
return false
}
}
print(Palindrome(readline()));
To check the string if it's a palindrome you just should compare it to its reversed version.
Say the word hello is not a palndrome because its reversed version olleh is not equal to it. But the word eye is a palindrome same as word abba because they're equal to their reversed versions.
Code example:
(function() {
var reverseStr,
isPalindrome,
testStrings;
reverseStr = function(str) {
var chars = [];
for(var i = str.length - 1; i > -1; i--) {
chars.push(str[i]);
}
return chars.join('');
};
isPalindrome = function(str, ignoreCase) {
if(ignoreCase) {
str = str.toLowerCase();
}
return str === reverseStr(str);
};
testStrings = ['abba', 'hello', 'eye'];
for(var i = 0, l = testStrings.length; i < l; i++) {
var word = testStrings[i];
console.log('Word "%s" is %sa palindrome',
word,
isPalindrome(word) ? '' : 'not ');
}
})();
DEMO #1
Another way that could work faster is listed below. Here you don't receive a reversed string to compare but walking towards the middle of the string from its start and its end.
var isPalindrome = function(str, ignoreCase) {
var length,
last,
halfLength,
i;
if(ignoreCase) {
str = str.toLowerCase();
}
length = str.length;
last = length - 1;
halfLength = Math.ceil(length / 2);
for(i = 0; i < halfLength; i++) {
if(str[i] !== str[last - i]) {
return false;
}
}
return true;
};
DEMO #2
function Palindrome(str) {
str = str.toLowerCase();
str = str.split(" ").join("");
return str == str.split("").reverse().join("");
}
This is what I ended up with. Made sure the string was all lowercase so it wouldn't read a potentially true parameter as false, got rid of the spaces, and then returned true/false based off whether or not the string was equal to it's reverse.
Here is an even easier way:
var isPalindrome = function(string) {
string = string.toLowerCase();
if(string.length===0){
return false;
}
for (var i = 0; i < Math.ceil(string.length/2); i++) {
var j = string.length-1-i;
var character1 = string.charAt(i);
var character2 = string.charAt(j);
if (character1 !== character2) {
return false;
}
}
return true;
};
I came across this palindrome coding challenge with a twist, you have to replace all the non-alphanumeric characters(punctuation, spaces and symbols) and of course change the string into lowercase. This is my solution.
function palindrome(str) {
var low = str.toLowerCase();
var filteredStr = low.replace(/[^0-9a-z]/gi, "");
var split = filteredStr.split("");
var backward = split.reverse();
var join = backward.join("");
if (filteredStr === join) {
return true;
} else {
return false;
}
}
if you care about number of lines of code, here's smaller one
function palindrome(str) {
var low = str.toLowerCase();
var filteredStr = low.replace(/[^0-9a-z]/gi, "");
var backward = filteredStr.split("").reverse().join("");
if (filteredStr === backward) {
return true;
} else {
return false;
}
}
the code is beginner friendly and self explanatory, but if you have any questions regarding the code, feel free to ask ;)

Javascript Function to split and return a value from a string

I am trying to grab a certain value. I am new to javascript and I can't figure out why this is not working.
If I parse "kid_2" I should get "kostas". Instead of "Kostas" I always get "02-23-2000". So I must have a logic problem in the loop but I am really stuck.
function getold_val(fieldname,str){
var chunks=str.split("||");
var allchunks = chunks.length-1;
for(k=0;k<allchunks;k++){
var n=str.indexOf(fieldname);
alert(chunks[k]);
if(n>0){
var chunkd=chunks[k].split("::");
alert(chunkd);
return chunkd[1];
}
}
}
var test = getold_val('kid_2','date_1::02-23-2000||date_2::06-06-1990||kid_1::George||kid_2::Kostas||');
alert(test);
A regex may be a little more appealing. Here's a fiddle:
function getValue(source, key){
return (new RegExp("(^|\\|)" + key + "::([^$\\|]+)", "i").exec(source) || {})[2];
}
getValue("date_1::02-23-2000||date_2::06-06-1990||kid_1::George||kid_2::Kostas||","kid_2");
But if you want something a little more involved, you can parse that string into a dictionary like so (fiddle):
function splitToDictionary(val, fieldDelimiter, valueDelimiter){
var dict = {},
fields = val.split(fieldDelimiter),
kvp;
for (var i = 0; i < fields.length; i++) {
if (fields[i] !== "") {
kvp = fields[i].split(valueDelimiter);
dict[kvp[0]] = kvp[1];
}
}
return dict;
}
var dict = splitToDictionary("date_1::02-23-2000||date_2::06-06-1990||kid_1::George||kid_2::Kostas||","||","::");
console.log(dict["date_1"]);
console.log(dict["date_2"]);
console.log(dict["kid_1"]);
console.log(dict["kid_2"]);​
This works, here's my fiddle.
function getold_val(fieldname,str) {
var chunks = str.split('||');
for(var i = 0; i < chunks.length-1; i++) {
if(chunks[i].indexOf(fieldname) >= 0) {
return(chunks[i].substring(fieldname.length+2));
}
}
}
alert(getold_val('kid_2', 'date_1::02-23-2000||date_2::06-06-1990||kid_1::George||kid_2::Kostas||'));
The issue with your code was (as #slebetman noticed as well) the fact that a string index can be 0 because it starts exactly in the first letter.
The code is almost the same as yours, I just didn't use the second .split('::') because I felt a .substring(...) would be easier.
There are two bugs. The first error is in the indexOf call:
var n = str.indexOf(fieldname);
This will always return a value greater than or equal to 0 since the field exists in the string. What you should be doing is:
var n = chunks[k].indexOf(fieldname);
The second error is in your if statement. It should be:
if(n >= 0) {
...
}
or
if(n > -1) {
...
}
The substring you are looking for could very well be the at the beginning of the string, in which case its index is 0. indexOf returns -1 if it cannot find what you're looking for.
That being said, here's a better way to do what you're trying to do:
function getold_val(fieldName, str) {
var keyValuePairs = str.split("||");
var returnValue = null;
if(/||$/.match(str)) {
keyValuePairs = keyValuePairs.slice(0, keyValuePairs.length - 1);
}
var found = false;
var i = 0;
while(i < keyValuePairs.length && !found) {
var keyValuePair = keyValuePairs[i].split("::");
var key = keyValuePair[0];
var value = keyValuePair[1];
if(fieldName === key) {
returnValue = value;
found = true;
}
i++;
}
return returnValue;
}

Categories

Resources