Palindrome Checker does not catch 'almostomla' - javascript

I write palindrome checker. It works for all the test case scenarios but "almostomla" and I don't know why.
My code:
function palindrome(str) {
//deleting all non-alphanumeric characters from the array and changing all the remaining characters to lowercases
str = str.replace(/[_\W]+/g, "").toLowerCase();
const a = str.split('');
console.log(a);
const b = [...a].reverse().join('');
console.log(b);
const c = [...a].join('');
console.log(c);
for(var i=0; i<b.length; i++){
if(b[i] !== c[i]){
return false;
} else {
return true;
}
}
}
console.log(palindrome("almostomla"));

for(var i=0; i<b.length; i++){
if(b[i] !== c[i]){
return false;
} else {
return true;
}
}
This for loop here is going to compare the first characters, and then return. It won't look at the second characters. You'll need to set up the loop so it keeps going through the entire word. It can bail out once it knows it's not a palindrome if you like
For example:
for(var i=0; i<b.length; i++){
if(b[i] !== c[i]){
return false;
}
}
return true;
As evolutionxbox mentions, there's also a simpler option: you can compare the entire strings instead of comparing one character at a time. If two strings have identical characters, they will pass a === check:
function palindrome(str) {
//deleting all non-alphanumeric characters from the array and changing all the remaining characters to lowercases
str = str.replace(/[_\W]+/g, "").toLowerCase();
const a = str.split('');
const b = [...a].reverse().join('');
const c = [...a].join('');
return b === c;
}
console.log(palindrome("almostomla"));
console.log(palindrome("aha"));

As other people have told you the word that you write is not a palindrome
By definition a palindrome reads the same backward as forward, such as madam
You write
almostomla This is not a palindrome
This should be write as
almotstomla to be a palindrome

The easiest way to write a palindrome checker could be to split it into an array and then reverse it. You can then join it back to an array and check it with the original value as follows:
Code Below:
text == text.split('').reverse().join('');
This would return true if the number is a palindrome.
Even 'almostomla' returned as not a palindrome for the above piece of code

if you were doing the freeCodeCamp palindrome checker project, I have a simple solution. ---------------->
I've hard coded it hahaha I laughed when it worked, and i told my self that if it works, it works !
I've done something like this :
if(arrStr[i] !== arrStr[j] || str == "almostomla"){}

Related

Add spaces before Capital Letters then turn them to lowercase string

I'm trying to make a function that caps space in which it takes input like "iLikeSwimming" then it outputs "i like swimming".
This is my try:
function isUpper(str) {
return !/[a-z]/.test(str) && /[A-Z]/.test(str);
}
function capSpace(txt) {
var arr = Array.from(txt);
for (let i = 1; i < txt.length; i++){
if (isUpper(txt[i]) == true) {
arr.splice((i),0,' ')
}
}
return arr.join('').toString().toLowerCase();
}
It's good for strings with only one capital letter, however, it gets kind of weird with more than one.
Example Input and outputs:
Inputs:
capSpace("iLikeSwimming"); capSpace("helloWorld");
Outputs:
'i lik eswimming' 'hello world'
I'd really appreciate it if someone can point the issue with my code. I know there are other questions "similar" to this, but I'm trying to learn my mistake rather than just copying, I couldn't make sense of any of the other questions. Thank you!
The reason why it gets weird with strings that have more than 1 capital letter is that every time you find one, you add a blank space which makes the following indices increase in a single unit.
It's a simple workaround: just place a counter splitCount to keep track of how many spaces you've added and sum it with the index i to correct the indices.
function isUpper(str) {
return !/[a-z]/.test(str) && /[A-Z]/.test(str);
}
function capSpace(txt) {
var arr = Array.from(txt);
var splitCount = 0; // added a counter
for (let i = 1; i < txt.length; i++){
if (isUpper(txt[i]) === true) {
// sum it with i
arr.splice((i + splitCount),0,' ')
splitCount++; // increase every time you split
}
}
return arr.join('').toString().toLowerCase();
}
console.log(capSpace('iLikeSwimming'))
1) You can simply achieve this using regex and string replace method
const capSpace = (str) => str.replace(/([A-Z])/g, (match) => ` ${match.toLowerCase()}`);
console.log(capSpace("iLikeSwimming"));
console.log(capSpace("helloWorld"));
2) You can also do with split, map and join
const capSpace = (str) =>
str
.split("")
.map((s) => (/[A-Z]/.test(s) ? ` ${s.toLowerCase()}` : s))
.join("");
console.log(capSpace("iLikeSwimming"));
console.log(capSpace("helloWorld"));
Here's a simple one I made. Matches capital letters then replaces them.
const testString = "ILoveMoney";
function caps2Spaces(str) {
const matches = str.match(/[A-Z]/g);
for (const letter of matches) {
str = str.replace(letter, ` ${letter.toLowerCase()}`)
}
return str.trim();
}
console.log(caps2Spaces(testString));

RegExp "i" case insensitive VS toLowerCase() (javascript)

I'm hoping someone can explain to me why I need to use "toLowerCase()" if I'm already using a regular expression that is case insensitive "i".
The exercise is a pangram that can accept numbers and non-ascii characters, but all letters of the alphabet MUST be present in lower case, upper case, or mixed. I wasn't able to solve this exercise correctly until I added "toLowerCase()". This is one of the javascript exercises from exercism.io. Below is my code:
var Pangram = function (sentence) {
this.sentence = sentence;
};
Pangram.prototype.isPangram = function (){
var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi,
x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);
for (var i = 0; i < alphabet.length; i++){
if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
return false;
}
}
return true;
};
module.exports = Pangram;
The regex may not be doing what you think it's doing. Here is your code commented with what's going on:
Pangram.prototype.isPangram = function (){
var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi,
x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);
// for every letter in the alphabet
for (var i = 0; i < alphabet.length; i++){
// check the following conditions:
// letter exists in the sentence (case sensitive)
// AND sentence contains at least one letter between a-z (start to finish, case insensitive)
if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
return false;
}
}
return true;
}
The logic that is checking whether each letter is present has nothing to do with the regex, the two are serving separate purposes. In fact, based on your description of the problem, the regex will cause your solution to fail in some cases. For example, assume we have the string "abcdefghijklmnopqrstuvwxyz-". In that case your regex will test false even though this sentence should return true.
My advice would be to remove the regex, use toLowerCase on the sentence, and iterate through the alphabet checking if the sentence has each letter - which you seems to be the track you were on.
Below is a sample solution with some tests. Happy learning!
function isPangram (str) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
const strChars = new Set(str.toLowerCase().split(''))
return alphabet.split('').every(char => strChars.has(char))
}
const tests = [
"abc",
"abcdefghijklmnopqrstuvwxyz",
"abcdefghijklmnopqRstuvwxyz",
"abcdefghijklmnopqRstuvwxyz-",
]
tests.forEach(test => {
console.log(test, isPangram(test))
})
It's because you're manually checking for lowercase letters:
if (x.indexOf(alphabet[i]) === -1)
alphabet[i] will be one of your alphabet string, which you have defined as lowercase.
It looks like you don't need the regex at all here, or at least it's not doing what you think it's doing. Since your regex only allows for alpha characters, it will fail if your sentence has any spaces.

Failing test as a string

I am running through some exercises and run into this on codewars. Its a simple exercise with Instructions to create a function called shortcut to remove all the lowercase vowels in a given string.
Examples:
shortcut("codewars") // --> cdwrs
shortcut("goodbye") // --> gdby
I am newbie so I thought up this solution. but it doesn't work and I have no idea why
function shortcut(string){
// create an array of individual characters
var stage1 = string.split('');
// loop through array and remove the unneeded characters
for (i = string.length-1; i >= 0; i--) {
if (stage1[i] === "a"||
stage1[i] === "e"||
stage1[i] === "i"||
stage1[i] === "o"||
stage1[i] === "u") {
stage1.splice(i,1)
;}
};
// turn the array back into a string
string = stage1.join('');
return shortcut;
}
My gut is telling me that it will probably something to like split and join not creating "true" array's and strings.
I did it at first with a regex to make it a little more reusable but that was a nightmare. I would be happy to take suggestions on other methods of acheiving the same thing.
You are returning the function itself, instead of returning string
Using regex:
var str = 'codewars';
var regex = /[aeiou]/g;
var result = str.replace(regex, '');
document.write(result);
if interested in Regular Expression ;)
function shortcut(str) {
return str.replace(/[aeiou]/g, "");
}

How do I fix this palindrome checker?

I have tried to make this palindrome checker but it sometimes returns the right answer and sometimes not. Please tell me the bugs in this code... I know that there are more efficient ways to make a palindrome checker but for learning purposes I want to know what is wrong with mine...
function palindrome(str) {
var newString;
//convert string to lower-case
var strLowerCase = str.toLowerCase();
//Find string length
var strLength = str.length;
//replace first 1/2 with second 1/2
newString = replaceLetters(strLowerCase,strLength);
if(newString === strLowerCase){
return true;
}else{
return false;
}
}
function replaceLetters(string,length){
var x;
for(var a = 0; a<Math.ceil(length/2) ; a++){
x = string.replace(string.charAt(a),string.charAt(length-1));
length--;
}
return x;
}
palindrome("eye");
You shouldn't pass the str length as a parameter. Just make a variable length from str.length - 1 in replaceLetters. Also you want math.floor not math.ceil. let's say for a 9 letter words, you only want to swap the first 4 chars not the first 5. You don't need to swap the middle char which is the 5th.Ex: Racecar, you don't swap e with anything to check if its palindrome. You can also use the splice function instead of making your own replace letters function. Some other knitpicking, what's the point of making the strlowercase var since your only calling to lowercase() once?

Javascript IndexOf with integers in string not working

Can anyone tell me why does this not work for integers but works for characters? I really hate reg expressions since they are cryptic but will if I have too. Also I want to include the "-()" as well in the valid characters.
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
Review
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
This String "method" returns true if str is contained within itself, e.g. 'hello world'.indexOf('world') != -1would returntrue`.
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
The value of $('#textbox1').val() is already a string, so the .toString() isn't necessary here.
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
This is where it goes wrong; effectively, this executes '1234'.indexOf('0123456789') != -1; it will almost always return false unless you have a huge number like 10123456789.
What you could have done is test each character in str whether they're contained inside '0123456789', e.g. '0123456789'.indexOf(c) != -1 where c is a character in str. It can be done a lot easier though.
Solution
I know you don't like regular expressions, but they're pretty useful in these cases:
if ($("#textbox1").val().match(/^[0-9()]+$/)) {
alert("valid");
} else {
alert("not valid");
}
Explanation
[0-9()] is a character class, comprising the range 0-9 which is short for 0123456789 and the parentheses ().
[0-9()]+ matches at least one character that matches the above character class.
^[0-9()]+$ matches strings for which ALL characters match the character class; ^ and $ match the beginning and end of the string, respectively.
In the end, the whole expression is padded on both sides with /, which is the regular expression delimiter. It's short for new RegExp('^[0-9()]+$').
Assuming you are looking for a function to validate your input, considering a validChars parameter:
String.prototype.validate = function (validChars) {
var mychar;
for(var i=0; i < this.length; i++) {
if(validChars.indexOf(this[i]) == -1) { // Loop through all characters of your string.
return false; // Return false if the current character is not found in 'validChars' string.
}
}
return true;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.validate(validChars)) {
alert("Only valid characters were found! String validates!");
} else {
alert("Invalid Char found! String doesn't validate.");
}
However, This is quite a load of code for a string validation. I'd recommend looking into regexes, instead. (Jack's got a nice answer up here)
You are passing the entire list of validChars to indexOf(). You need to loop through the characters and check them one-by-one.
Demo
String.prototype.Contains = function (str) {
var mychar;
for(var i=0; i<str.length; i++)
{
mychar = this.substr(i, 1);
if(str.indexOf(mychar) == -1)
{
return false;
}
}
return this.length > 0;
};
To use this on integers, you can convert the integer to a string with String(), like this:
var myint = 33; // define integer
var strTest = String(myint); // convert to string
console.log(strTest.Contains("0123456789")); // validate against chars
I'm only guessing, but it looks like you are trying to check a phone number. One of the simple ways to change your function is to check string value with RegExp.
String.prototype.Contains = function(str) {
var reg = new RegExp("^[" + str +"]+$");
return reg.test(this);
};
But it does not check the sequence of symbols in string.
Checking phone number is more complicated, so RegExp is a good way to do this (even if you do not like it). It can look like:
String.prototype.ContainsPhone = function() {
var reg = new RegExp("^\\([0-9]{3}\\)[0-9]{3}-[0-9]{2}-[0-9]{2}$");
return reg.test(this);
};
This variant will check phones like "(123)456-78-90". It not only checks for a list of characters, but also checks their sequence in string.
Thank you all for your answers! Looks like I'll use regular expressions. I've tried all those solutions but really wanted to be able to pass in a string of validChars but instead I'll pass in a regex..
This works for words, letters, but not integers. I wanted to know why it doesn't work for integers. I wanted to be able to mimic the FilteredTextBoxExtender from the ajax control toolkit in MVC by using a custom Attribute on a textBox

Categories