Javascript function that checks whether number is palindrome - javascript

I read through a few of palindrome questions posted here, but unfortunately couldn't find a way to fix mine. An example of what I'm trying to achieve:
Input: 989
Output: "It's a palindrome"
Input: 23
Output: "Not a palindrome"
Input: 9
Output: "It's a palindome" (any single digit)
My try
function Palindrome(num) {
let numToStringArray = num.toString().split('');
let reversedArray = numToStringArray.reverse();
if (num.toString().length<2) {
return "It's a palindrome"
}
else {
for (let i = 0; i<numToStringArray; i++;) {
if (numToStringArray[i] !== reversedArray[i]) {
return "It's not a palindrome"
}
else {
return "It's a palindrome"
}
}
}
}
When invoked, the function only works for single-digit strings. I tried to fix my for-loop, as I feel that the problem lies in the following line:
if (numToStringArray[i] !== reversedArray[i])
but could not come up with a working solution. Thanks for reading or even helping me out!

I'm spotting several problems...
First, you don't want a ; after your i++ in the loop definition. In jsFiddle at least, that's resulting in a syntax error. Other environments may be more forgiving, but it's worth fixing.
Second, the loop condition is wrong:
i < numToStringArray
should be:
i < numToStringArray.length
Third, the logic of the loop is a bit broken. You're returning "It's a palindrome" immediately if the very first pair match. So by that logic "1231" is a palindrome. Instead, only return within the loop if you find that it's not a palindrome. If the loop completes without returning, then return that it's a palindrome:
for (let i = 0; i < numToStringArray.length; i++) {
if (numToStringArray[i] !== reversedArray[i]) {
return "It's not a palindrome";
}
}
return "It's a palindrome";

Made this quick & working solution:
function checkPalindrome(num) {
var numString = num.toString();
return numString.split("").reverse().join("") == numString;
}
Provide an integer parameter inside the checkPalindrome() function, and it will return either true or false.
For example:
if (checkPalindrome(123321)) {
console.log("Is a palindrome");
} else {
console.log("Not a palindrome");
}

How about this
str === str.split('').reverse().join("")
like so
const palindrome = num => {
const str = num.toString();
return `It's ${str.length<2 || str === str.split('').reverse().join("") ? "" : "not "}a palindrome`
};
console.log(
[989, 23, 9].map(num => `${num}: ${palindrome(num)}`)
)

actually your numToStringArray is not reversing. Try this:
function Palindrome(num) {
let numToStringArray = num.toString().split('');
let reversedArray = num.toString().split('').reverse();
console.log("here", numToStringArray, reversedArray)
if (num.toString().length<2) {
return "It's a palindrome"
}
else {
for (let i = 0; i<numToStringArray.length; i++) {
if (numToStringArray[i] !== reversedArray[i]) {
return "It's not a palindrome"
}
else {
return "It's a palindrome"
}
}
}
}
console.log(Palindrome(686))

The reason your logic doesn't is mainly due to the fact that you use i < numToStringArray instead of i < numToStringArray.length as mentioned in the comments.
The simplest way to achieve what you want though, would simply be-
function isPalindrome(num) {
return num === Number(num.toString().split('').reverse().join(''));
}

This should work.
const pal = num => {
let reversedNum = parseFloat(num.toString().split('').reverse().join(''));
if (reversedNum === num) {
console.log("palindrome")
} else {
console.log("no palindrome")
}
}
pal(12121);

Without using split, reverse and join, it can be checked through a single array.
function Palindrome(num) {
let numToStringArray = num.toString();
var len = numToStringArray.length;
if (len < 2) {
return "It's a palindrome"
}
else {
for (var i = 0; i < len / 2; i++) {
if (numToStringArray[i] !== numToStringArray[len - 1 - i]) {
return "It's not a palindrome";
}
return "It's a palindrome"
}
}
}
console.log(Palindrome(989));
console.log(Palindrome(23));
console.log(Palindrome(9));

A short function to test if the number is a Palindrome and returns a "true" or "false" is as follows:
You can then call it and output your text result "It's a palindrome" in case it returns true or "Not a palindrome" if returns false.
Test examples provided below.
const IsPalindrome = e => (e+="").split("").reverse().join("") == e;
// ======== test =============
console.log(IsPalindrome(23)); // false
console.log(IsPalindrome(121)); // true
console.log(IsPalindrome(9889)); // true
console.log(IsPalindrome(989)); // true
console.log(IsPalindrome(1)); // true

To meet your specific requirements for the output text. Here is a one-liner function based on the function below:
function IsPalindrome(n) {
return n + (((n+="").split("").reverse().join("") == n) ? " is a palindrome" : " is not a palindrome");
}
// ======== test =============
console.log(IsPalindrome(23)); // 23 is not a palindrome
console.log(IsPalindrome(121)); // 121 is a palindrome
console.log(IsPalindrome(9889)); // 9889 is a palindrome
console.log(IsPalindrome(989)); // 989 is a palindrome
console.log(IsPalindrome(1)); // 1 is a palindrome

Taking advantage of its function, something you could do after using the split method and the reverse method to read the number from right to left, is to use the join to transform it into a string again and then compare them, like this:
function Palindrome(num) {
let numToStringArray = num.toString().split('');
let reversedArray = numToStringArray.reverse().join('');
if (num.toString() == reversedArray)
console.log('It\'s a palindrome');
else
console.log('It\'s not a palindrome');
}
Palindrome(9);
Palindrome(232);
Palindrome(152);

let a, b = 121;
a = b;
console.log(String(b).split("").reverse().join() === String(a).split("").join());

Related

Getting undefined, and can't find the bug

I'm having trouble finding the bug in my program. The console.logs labelled "Debug 3" and "Debug 6" are both returning undefined. I'm sure it's obvious, but any help pointing them out would be much appreciated. I'm also still pretty new, so if you have any suggestions about a different way I should have done this, I'm open to the feedback!
I know I could have just written a bunch of if/else statements, but I really wanted to give an honest go at making the code modular, and as reusable as possible.
Side note: I know that my function/variable names are trash. I plan on renaming them all once the program is working properly. This was just easier to help keep track (though obviously that didn't work out very well, hence here I am).
The code I have so far is:
// ---------------------- INPUT CHECKS ---------------------- //
// Check and return the number of words supplied in the name
const checkNameLength = (name) => {
arr = name.split(' ');
return arr.length;
};
// Checks if the name contains any spaces on the edges
const checkForSpacesOnEdges = (name) => {
if (name[0] === ' ' || name[-1] === ' ') {
return true;
} else {
return false;
}
};
// Checks if the name contains an honorific
const checkIfContainsHonorific = (name) => {
let accumulator = 0;
let result;
for (let i = 0; i < name.length; i++) {
if (name[i] === '.') {
accumulator++;
}
}
if (accumulator !== 0) {
result = true;
} else {
result = false;
}
return result;
};
// Returns a 1 word string
const isSingleName = (name) => {
let result;
let arr = name.split(' ');
if (arr.length === 1) {
result = true;
} else {
result = false;
}
return result;
};
// ---------------------- OUTPUT ---------------------- //
// Return empty string
const emptyOutput = (name) => {
return 'empty string';
};
// Returns the exact string provided by user
const returnAsIs = (name) => {
return name;
};
// Returns the name with trailing spaces removed
const returnWithoutSpaces = (name) => {
return name.trim();
};
// Reverses the name string and returns it
const normalReverse = (name) => {
let arr = [];
let result;
arr = name.split(' ');
arr.reverse();
result = arr[0] + ', ' + arr[1];
result.toString();
return result;
};
// Reverses the first and last name, but leaves the honorific in front
const hasHonorificReverseNames = (name) => {
let arr = name.split(' ');
let firstAndLastArr = [];
for (let i = 1; i < arr.length; i++) {
firstAndLastArr.push(arr[i]);
}
firstAndLastArr.reverse();
return arr[0].toString() + firstAndLastArr[0].toString() + ', ' + firstAndLastArr[1].toString();
};
// Main func
const nameInverter = (name) => {
let result;
if (!name) {
result = emptyOutput(name);
} else if (isSingleName(name)) {
result = returnAsIs(name);
} else if (!checkIfContainsHonorific(name)) {
if (checkForSpacesOnEdges(name)) {
result = returnWithoutSpaces(name);
}
} else if (checkNameLength(name) === 1) {
if (checkIfContainsHonorific(name)) {
result = emptyOutput(name);
}
} else if (checkNameLength(name) === 2) {
console.log("Flag 1: ", name);
if (!checkIfContainsHonorific(name)) {
console.log("Flag 2: ", name);
result = name;
}
} else if (checkNameLength(name) === 2) {
if (checkIfContainsHonorific(name)) {
result = returnAsIs(name);
}
} else if (checkNameLength(name) === 3) {
if (checkIfContainsHonorific(name)) {
result = hasHonorificReverseNames(name);
}
} else {
return normalReverse(name);
}
return result;
};
console.log("Debug 1", nameInverter(''));
console.log("Debug 2", nameInverter('Ronald'));
console.log("Debug 3", nameInverter('Ronald McDonald'));
console.log("Debug 4", nameInverter(' Ronald McDonald '));
console.log("Debug 5", nameInverter('Dr. Ronald McDonald'));
console.log("Debug 6", nameInverter('Dr. Ron'));
The output that I'm getting from those console.logs (including the Flag 1 console.log in the function I suspected was causing problems, is listed below:
Debug 1 empty string
Debug 2 Ronald
Debug 3 undefined
Debug 4 Ronald McDonald
Debug 5 Dr.McDonald, Ronald
Flag 1: Dr. Ron
Debug 6 undefined
Thank you, any guidance is greatly appreciated!
So you're issue here is that you're actually reaching some of your if else statements, but then not setting the code within that code block.
Anytime you're getting undefined here, is because you're not setting result to anything.
if else statements won't 'fall through' so as soon as one is true, it will run that block of code, but not the following blocks.
A good example is with your 'debug 3' 'Ronald Mcdonald' check. It goes into your if else statements, and hits the has length === 2 test, but then in that code block, you do another test to see if it contains 'Dr.' and if it does then set result to name, but if this check fails, you're never setting result to the name.
Essentially you either need to order your if else statements so that they can be checked in order and they won't conflict or you need to nest additional if else statements within those checks for length to check for the other things that you want to.

check if text is a subset of a serie

I want to check a string against a serie (with respect to order)
-- see bellow for another approach (string solution)
Regex solution (potential)
r = /[(qw|az)ert(y|z)uiop(é|å|ü)]{5}/g
str = "ertyu"
str2 = "rtrrr"
r.test(str) // true
r.test(str2) // true
The str2 should return false as it does not respect the order, but since the regex is wrapped in array I assume this approach is wrong from the start.
String solution
arr = [
"qwertyuiopé",
"qwertyuiopå",
"qwertyuiopü",
"qwertzuiopé",
"qwertzuiopå",
"qwertzuiopü",
"azertyuiopé",
"azertyuiopå",
"azertyuiopü",
"azertzuiopé",
"azertzuiopå",
"azertzuiopü",
]
str = "ertyu"
str2 = "yrwqp"
function test(s) {
for (const a of arr) {
if (a.indexOf(str) >= 0) return true
}
return false
}
test(str) // true
test(str2) // false
The string version works but its ugly and big
Is there a way with regex to get this working?
In the end I don't think what I want to achieve would be possible,
I ended up with an array of different series (keyboard trivial series)
and a function that checks if a password is a sequence of the series
const trivialseries = [
// swedish, german, french, english, spanish, italian - keyboard
"1234567890",
"qwertyuiopå", // se|en
"asdfghjklöä",
"zxcvbnm",
"qwertzuiopü", // de
"yxcvbnm",
"azertyuiop", // fe
"qsdfghjklmù",
"wxcvbn",
"asdfghjklñ", // sp
"qwertyuiopé", // it
"asdfghjklòàù",
];
const MAX = 5;
function subsequence(serie, str) {
for (let i = 0; i < str.length - MAX + 1; i++) {
const index = serie.indexOf(str[i]);
if (index >= 0) {
let found = 1;
for (let j = i + 1; j < str.length; j++) {
if (serie[index + found] === str[j]) found++;
else break;
if (found === MAX) return true;
}
}
}
return false;
}
function isTrivial(password) {
for (let ts of trivialseries) {
if (subsequence(ts, password)) return true;
const reverse = ts.split("").reverse().join("");
if (subsequence(reverse, password)) return true;
}
return false;
}
console.log(isTrivial("e927ncsmnbvcdkeloD€%s567jhdoewpm")); // true "mnbvc" is reverse form of "cvbnm"

How to return values from functions into other functions

I'm trying check if a number is a palindrome in Javascript
I've converted a number to a string, and reversed it and saved it as a new variable: reverseNum. However, when I go to check if num == reverseNum, i can't seem to get the logic to work properly
function palindrome() {
function reverse(num) {
num = num.toString();
let reverseNum = [];
for (let i = 1; i <= num.length; i++) {
reverseNum.push(num[num.length - i]);
}
return reverseNum.join('');
}
function check(num, reverseNum) {
//is palindrome
if (num == reverseNum) {
return true;
//is not palindrome
} else {
return false;
}
}
}
console.log(palindrome(121));
expected output should be true if for example input: 121, output: 121
expected output should be false if for example input: 79, output: 97
As the comments suggest, this really just boils down to not passing a value into the function palindrome and then not returning anything from it. As such this is quite a quick fix:
function palindrome(number) {
function reverse(num) {
num = num.toString();
let reverseNum = [];
for (let i = 1; i <= num.length; i++) {
reverseNum.push(num[num.length - i]);
}
return reverseNum.join('');
}
function check(num, reverseNum) {
//is palindrome
if (num == reverseNum) {
return true;
//is not palindrome
} else {
return false;
}
}
return check(number, reverse(number))
}
console.log(palindrome(1211));
This can be done with a little less code, by converting the number to an array, reversing, and then checking it:
const palindrome = number => `${number}` === `${number}`
.split('')
.reverse()
.join('')
console.log(palindrome(121))
console.log(palindrome(1211))
Edit
To explain further, as requested.
I did think about converting this to standard functions in order to try and make it a little clearer, but I think it would be better to explain what's going on.
${number} just converts our number to a string. We want to do that so that we can more easily convert it to an array.
We want to convert it to an array because arrays have a reverse method, which is just what we need. So, in order to get a reversed array, we can use:
`${number}`
.split('')
.reverse()
So now we have an array which is the characters of our number reversed. We now need to get that into a form which we can use to compare to the original number. To do that, we can get it back to a string using join(). Now we have a reversed string of the initial number. Now, we just need to compare that to the initial number to see if we have a palindrome.
As it's not really ideal to compare a number to a string, we need to convert one of them. In my example, I've converted the initial number to a string using ${number}.
The arrow syntax is just shorthand for a standard function (though there are some other differences which are not relevant for now).
Because the methods we use take in an array, and return an array, we can chain them together to make the code nice and simple.
In summary:
// convert our numbers to strings
`${number}` === `${number}`
// split the string into an array
.split('')
// reverse the array
.reverse()
// convert the array back to a string
.join('')
If you have any specific questions, just let me know!
I created separate functions. Hopefully this helps.
function reverse(num) {
num = num.toString();
var reverseNum = [];
for (var i = 1; i <= num.length; i++) {
reverseNum.push(num[num.length - i]);
}
return reverseNum.join('');
}
function palindrome(num) {
var reverseNum = parseInt(reverse(num));
console.log("Num:", num);
console.log("Reverse Num:", reverseNum);
if (num === reverseNum)
return true;
//is not palindrome
else
return false;
}
console.log(palindrome(121));
You don't need two functions for this. Just a single function palindrome() is sufficient to check for palindromes.
Convert the parameter num into a string.
Assign numString to an empty string.
Push every character of the num string to the numString string.
Check if the new string numString is the same as the initial num string.
function palindrome(num) {
num = num.toString();
let reverseNum = "";
for(i = 1; i <= num.length; i++) {
reverseNum += num.charAt(num.length - i);
}
if (num == reverseNum) {
console.log(num + " is a Palindrome!!");
return true;
} else {
console.log(num + " is not a Palindrome!!");
return false;
}
}
palindrome(224);
palindrome(424);
palindrome(222);
palindrome(363);
This will do
function palindrome(num) {
num = num.toString();
let reverseNum = [];
for (let i = 1; i <= num.length; i++) {
reverseNum.push(num[num.length - i]);
}
var e=reverseNum.join('')
alert(e)
return check(num,e);
}
function check(num, reverseNum) {
//is palindrome
if (num == reverseNum) {
return true;
//is not palindrome
} else {
return false;
}
}
alert(palindrome(121));
You didn't return the check function and there is error with your function scopes.

Check if second string is rotation of another string

I'm trying to write a function that takes in two string parameters and check if the second parameter is a rotated version of the first string.
So the following would be the results:
checkRotationStrings('waterbottle', 'lewaterbott'); // true
checkRotationStrings('waterbottle', 'bottlewater'); // true
checkRotationStrings('waterbottle', 'erbottlewat'); // true
checkRotationStrings('waterbottle', 'lewaterbottx'); // false
I wrote the following code, but there are some edge cases that I can't seem to figure out:
function checkRotationStrings(string, rotatedString) {
let result;
let rotationCheck
let stringArr = string.split('');
let rotatedStringArr = rotatedString.split('')
for (let i = 0; i < string.length - 1; i++) {
if (rotatedString[0] === stringArr[i]) {
result = stringArr.slice(i);
rotationCheck = stringArr.slice(0, i).concat(result).join('');
}
}
console.log(rotationCheck)
if (rotationCheck === string){
return true;
} else {
return false;
}
}
Any help would be appreciated.
You could use String#repeat with rotated and two as parameter and check with String#includes.
function checkRotationStrings(string, rotated) {
return string.length === rotated.length && rotated.repeat(2).includes(string);
}
console.log(checkRotationStrings('waterbottle', 'lewaterbott')); // true
console.log(checkRotationStrings('waterbottle', 'bottlewater')); // true
console.log(checkRotationStrings('waterbottle', 'erbottllewat')); // false
console.log(checkRotationStrings('waterbottle', 'lewaterbottx')); // false
console.log(checkRotationStrings('waterbottle', 'ttlewaterb')); // false
You could use substring and rotate until you find a match. Like this:
function checkRotationStrings(string, rotatedString) {
let match = false;
for (let i = 0;
(i < string.length - 1) & !match; i++) {
match = rotatedString.substring(i, rotatedString.length) + rotatedString.substring(0, i) === string;
}
return match
}
console.log(checkRotationStrings('waterbottle', 'lewaterbott')); // true
console.log(checkRotationStrings('waterbottle', 'bottlewater')); // true
console.log(checkRotationStrings('waterbottle', 'erbottlewat')); // true
console.log(checkRotationStrings('waterbottle', 'lewaterbottx')); // false
This is a somewhat strange solution, as it uses some only for the index parameter. But each iteration in some simply compares two strings, one which is a rotation of the first, and the other is the second one.
const checkRotationStrings = (str, rot) =>
str.split('').some((s, i) => str.slice(i) + str.slice(0, i) == rot);
[
['waterbottle', 'lewaterbott'], // true
['waterbottle', 'bottlewater'], // true
['waterbottle', 'erbottllewat'], // false -- ORIGINAL
['waterbottle', 'erbottlewat'], // true -- CORRECTED
['waterbottle', 'lewaterbottx'] // false
].forEach(([s, r]) => console.log(`'${s}', '${r}': ${checkRotationStrings(s, r)}`))
You can do the following:
checkRotationStrings(str1: string, str2: string) {
if (str1.length !== str2.length) {
return false;
} else {
for (var i = 0; i < str2.length; i++) {
if (str2[i] === str1[0]) {
var substring1 = str2.substring(0,i);
var substring2 = str2.substring(i,str2.length);
var concatWord = substring2.concat(substring1);
if(str1 === concatWord){
console.log(str1 + " matches " + concatWord)
return true;
}else{
console.log(str1 + " not matches " + concatWord)
}
}
}
return false;
}
}
Stack Overflow questions often receive answers in the form of completely new code (and/or ideas) on how to achieve the desired result. Usually, there's at least an attempt to help the questioner with their actual question, which in this case seemed to ask for some help with your code (one issue at least had to do with "slicing," as you commented).
I also love to offer new code or ideas if I particularly like it so I'm only partly critical here, but the answers so far have suffered from a complete lack of relating to the question.
There's nothing wrong with how you have conceived of checking for string rotation. You just have a couple of bugs:
First, since rotationCheck is meant to rotate string in order to compare it with rotatedString, you got the string-building reversed. It should be:
rotationCheck = result.concat(stringArr.slice(0, i)).join('');
Secondly, once you've built the rotation-check, you need to compare it with rotatedString, not string. So:
if (rotationCheck === rotatedString){
I might be late for this, but here is my solution and it include all edge cases.
function checkRotation(str1,str2){
const char0 = str1[0];
let ind = str2.indexOf(char0);
while(ind>-1){
const start = str2.substring(0,ind);
const end = str2.substring(ind,str2.length);
if(end+start === str1){
return true;
}
ind = str2.indexOf(char0,ind+1)
}
return false
}
console.log(checkRotation("assads","adsass"))
Instead of trying to break it in random pieces and do different checks, you could instead do a count of the letters. This would be much simpler:
const countLetters = a => Array.prototype.reduce.call(a, (r, l) => Object.assign(r, { [l]: (r[l] || 0) + 1 }), {});
function checkRotatedString(a, b) {
const countA = countLetters(a);
const countB = countLetters(b);
return Object.keys(countA).length === Object.keys(countB).length
&& Object.entries(countA).every(([key, value]) => value === countB[key]);
}
// Tests
[['waterbottle', 'lewaterbott'], ['waterbottle', 'bottlewater'], ['waterbottle', 'erbottlewat'], ['waterbottle', 'lewaterbottx']]
.forEach(a => console.log(a, checkRotatedString.apply(null, a)));

Javascript How to identify if all elements of one array are present in another

I need to create a function to check if all the letters in the second string of a two string array are present in the first string. The function I wrote seems to work for most of the examples I tried with it but ["hello" , "hey"] returns true despite there not being a y in hello and I don't understand why.
Here's my code:
function mutation(arr) {
arr[0] =arr[0].toUpperCase().split("");
arr[1] =arr[1].toUpperCase().split("");
for(i=0;i<arr[1].length;i++){
if(arr[0].indexOf(arr[1][i])>=0){
return true;
} else {return false;}}}
mutation(["hello", "Hey"]);
You are returning true even if one character is matched ,Try below code it checks if all characters are present or not
function mutation(arr) {
arr[0] = arr[0].toUpperCase().split("");
arr[1] = arr[1].toUpperCase().split("");
var count = 0;
for (i = 0; i < arr[1].length; i++) {
if (arr[0].indexOf(arr[1][i]) >= 0) {
count++;
}
}
return count === arr[1].length
}
mutation(["hello", "Hey"]);
here is one more efficient solution, it works only for lowercase letters.
(function(){
function charCode(str, i){
return str.charCodeAt(i) - 97;
}
function isMutation(a,b){
const aArr = new Uint8Array(26);
const bArr = new Uint8Array(26);
let i=0;
let index = 0;
while(i<a.length){
++aArr[charCode(a, i)];
++i;
}
i = 0;
while(i<b.length){
++bArr[charCode(b, i)];
++i;
}
i = 0;
while(i < 26){
if(!(aArr[i]===0 && bArr[i]===0 || aArr[i]>0 && bArr[i]>0)){
return false
}
++i;
}
return true;
}
console.assert(isMutation('hello', 'oleh') === true);
console.assert(isMutation('hello', 'hey') === false);
})();
you can also compare sum of uniq chars in the both arrays, but in this case you have to add each letters only once.
I would recommend using one of the code solutions suggested by user georg at Remove Duplicates from JavaScript Array.
For example, the function below could be used to sort each array (arr[0] and arr[1]) and remove duplicates.
Credit to user georg at the link above.
function uniq(a) {
return a.sort().filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
})
}
Once you have sorted/removed duplicates, you can test to see if the two returned strings are equal or not.
Hello => EHLO, and Hey => EHY
EHLO !== EHY

Categories

Resources