Recursive palindrome check with JavaScript - javascript

I am trying to find out whether a string is a palindrome by recursion using javascript. But I can't figure out what I am missing in the code.
var firstCharacter = function(str) {
return str.slice(0, 1);
};
var lastCharacter = function(str) {
return str.slice(-1);
};
var middleCharacters = function(str) {
return str.slice(1, -1);
};
var isPalindrome = function(str) {
if(str.length < 2) {
return true;
} else {
if(firstCharacter(str) == lastCharacter(str)) {
isPalindrome(middleCharacters(str));
} else return false;
}
};
var checkPalindrome = function(str) {
console.log("Is this word a palindrome? " + str);
console.log(isPalindrome(str));
};
checkPalindrome("a");
//Program.assertEqual(isPalindrome("a"), true);
checkPalindrome("matom");
//Program.assertEqual(isPalindrome("motor"), false);
checkPalindrome("rotor");
//Program.assertEqual(isPalindrome("rotor"), true);
For sure something is wrong with the recursive call. I would love to have your help. Thanks. I am attaching the output of my code.

Here is another recursive palindrome.
function checkPalindrome(str){
if(str.length === 1) return true;
if(str.length === 2) return str[0] === str[1];
if(str[0] === str.slice(-1)) return checkPalindrome(str.slice(1,-1))
return false;
}
console.log(checkPalindrome('a')) // true
console.log(checkPalindrome('matom')) // false
console.log(checkPalindrome('rotor')) // true

You defined isPalindrome() to return a value, so if you call it yourself, recursively or otherwise, you need to deal with that return value. Also, your if ... else logic is too complicated, simplify:
var isPalindrome = function(str) {
if (str.length < 2) {
return true;
}
if (firstCharacter(str) == lastCharacter(str)) {
return isPalindrome(middleCharacters(str));
}
return false;
};

const isPalindrome = str => {
const strLen = str.length;
if (strLen < 2) return true;
if (str[0] === str[strLen - 1]) {
return isPalindrome( str.slice(1, strLen - 1) );
}
return false;
};
console.log(isPalindrome('madam'));

Using slice creates an array - if you want to compare the first and last char, you will need to extract the value from the array before applying == -
var firstCharacter = function(str) {
return str.slice(0, 1)[0] // <-- get the first element of the slice
}
var lastCharacter = function(str) {
return str.slice(-1)[0] // <-- get the first element of the slice
}
Here's another recursive solution that uses parameters l (left) and r (right) to check the string using indexes (rather than creating intermediate values with slice) -
const palindrome = (s = "", l = 0, r = s.length - 1) =>
r - l < 2
? true
: s[l] === s[r] && palindrome (s, l + 1, r - 1)
console.log
( palindrome ("motor") // false
, palindrome ("rotor") // true
, palindrome ("racecar") // true
, palindrome ("wow") // true
, palindrome ("i") // true
)
And here's a mutually recursive definition. It's wasteful but it has an elegant form nonetheless -
const pal = ([ s, ...more ]) =>
more.length === 0 || pal2 (more.reverse(), s)
const pal2 = ([ s, ...more ], q) =>
s === q && pal (more.reverse())
console.log
( pal ("motor") // false
, pal ("rotor") // true
, pal ("racecar") // true
, pal ("wow") // true
, pal ("i") // true
)

Here is another way to recursively check for a palindrome in JS:
function isPalindrome(str){
if (str[0] === str[str.length - 1] && str.length > 1) {
isPalindrome(str.substring(1, str.length -1))
return true
}else{
return false
}
}

Here's a simple answer for ya. Basically we are comparing the first character to last character and acting accordingly.
const isPalindrome = str => {
if (str.length <= 1) return true;
if (str[0] !== str[str.length - 1]) return false;
return isPalindrome(str.slice(1,-1))
}

const isPalindrome = str => {
// base case
if(str.length === 1) return true;
if(str.length === 2) return str[0] === str[1];
if(str[0] === str[str.length - 1]) {
return isPalindrome(str.slice(1, -1))
}
return false;
}
you can use recursion
base case
we have a base case (the simple case) if the string is one char we simply returns true.
if it has two chars we check if the first char is identical to the second and we return true if they are.
recursive case
if it is more than two chars we check if the first and last chars are identical or not if they are not we simply return false
but if they are identical so we now want to do the same thing with other chars so we call the same function with the same string but removing the first and last chars because we already know that they are identical and we keep going until we reach the base case.
hope this be useful
some tests
isPalindrome('p') // true
isPalindrome('po') // false
isPalindrome('pp') // true
isPalindrome('pop') //true

What's about this solution ?
function isPalindrome(str){
if (str.length > 3) return isPalindrome(str.substring(1, str.length-1));
return str[0] === str[str.length-1];
}

My simple implementation for a recursive palindrome check, in 2022:
function isPalindrome(str) {
if (!str.length || str.length === 1) return true;
return str[0] === str.at(-1) ? isPalindrome(str.substr(1, str.length - 2)) : false;
}
console.log(isPalindrome('catotac'));
Iterations breakdown:
// 1st iteration:
isPalindrome('catotac');
//2nd iteration
isPalindrome('atota');
//3rd
isPalindrome('tot');
// 4th iteration
isPalindrome('o'); // true

Related

check the alphabetical order

I am a newbie who is trying hard to have a grip on javascript. please help me to consolidate my fundamentals.
input will be a string of letters.
following are the requirements.
function should return true if following conditions satisfy:
letters are in alphabetical order. (case insensitive)
only one letter is passed as input. example :
isAlphabet ('abc') === true
isAlphabet ('aBc') === true
isAlphabet ('a') === true
isAlphabet ('mnoprqst') === false
isAlphabet ('') === false
isAlphabet ('tt') === false
function isAlphabet(letters) {
const string = letters.toLowerCase();
for (let i = 0; i < string.length; i++) {
const diff = string.charCodeAt(i + 1) - string.charCodeAt(i);
if (diff === 1) {
continue;
} else if (string === '') {
return false;
} else if (string.length === 1) {
return true;
} else {
return false;
}
}
return true;
}
It's generally a better practice to start your function off with dealing with the edge-cases rather than putting them somewhere in the middle. That way, the function returns as soon as it can - and it's a lot easier to read than a waterfall of if..else statements.
function isAlphabet(letters) {
if ("" == letters) {
return false;
}
if (1 == letters.length) {
return true;
}
const string = letters.toLowerCase();
// carry on with your loop here.
}
You've got the right idea, but it can be simplified to just fail on a particular error condition, i.e when a smaller character follows a larger one:
function isAlphabet(letters) {
const string = letters.toLowerCase();
let lastChar;
for (let i = 0; i < string.length; i++) {
// Grab a character
let thisChar = string.charCodeAt(i);
// Check for the failure case, when a lower character follows a higher one
if (i && (thisChar < lastChar)) {
return false;
}
// Store this character to check the next one
lastChar = thisChar;
}
// If it got this far then input is valid
return true;
}
console.log(isAlphabet("abc"));
console.log(isAlphabet("aBc"));
console.log(isAlphabet("acb"));
You can use the simple way to achieve the same as below
function isAlphabet(inputString)
{
var sortedString = inputString.toLowerCase().split("").sort().join("");
return sortedString == inputString.toLowerCase();
}
console.log("abc = " + isAlphabet("abc"));
console.log("aBc = " + isAlphabet("aBc"));
console.log("acb = " + isAlphabet("acb"));
console.log("mnoprqst = " + isAlphabet("mnoprqst"));
Note: Mark the answer is resolves your problem.

Recursively add to strings in JS

I'm tackling a recursion problem that returns a string of "hi"'s where the first "hi" has a capital H and the string ends with an exclamation point. I have the code below so far but I'm not sure how to prevent subsequent occurrences of "hi" having a capital H. Any guidance would be welcome.
function greeting(n) {
if (n === 0) {
return "";
} else if (n === 1) {
return "Hi!"
} else {
return `${'Hi' + greeting(n - 1)}`
}
}
console.log(greeting(3)) // should return Hihihi!
console.log(greeting(5)) // should return Hihihihihi!
One way to work around your problem is to pass a flag to the function which indicates whether this is the first call, and only in that case capitalise the hi. Note that you can simplify the code slightly by returning a ! when n == 0; then you don't need to special case n == 1:
function greeting (n, first = true) {
if (n === 0) {
return "!";
}
else {
return `${(first ? 'Hi' : 'hi') + greeting(n - 1, false)}`
}
}
console.log(greeting(3)) // should return Hihihi!
console.log(greeting(5)) // should return Hihihihihi!
Just a .toLowerCase() is missing in your code.
`${'Hi' + greeting(n - 1).toLowerCase()}`
You don't need the n === 1 step.
function greeting(n) {
if (n === 0) {
return "!";
} else {
return `${'Hi' + greeting(n - 1).toLowerCase()}`
//------------------------------^^^^^^^^^^^^^^
}
}
console.log(greeting(3)) // should return Hihihi!
console.log(greeting(5)) // should return Hihihihihi!

find multiple (2) elements in a string in javascript

I want to return whether one of the conditions exist within findAB(str) as boolean
A 5 letter long string which starts with 'a' ends with 'b'
A 5 letter long string which starts with 'b' ends with 'a'
function findAB(str) {
let lowerSTR = str.toLowerCase()
let indexOFa = lowerSTR.indexOf('a')
let indexOFb = lowerSTR.indexOf('b')
if (lowerSTR[indexOFa + 4] === 'b' || lowerSTR[indexOFb + 4] === 'a') {
return true;
}
return false;
}
I first changed strings into lower case using .toLowerCase() method and defined indexOFa and indexOFb.
I thought simply by doing index of a + 4 will turn out true but in fact it doesn't and cannot figure out what I did wrong.
I also know some method to find elements in an array such as find(), includes(), map() or filter but not sure if I can use it since it is not an array.
If you want to change your approach you can use regex like this
function findAB(str) {
let case1 = str.match(/a[a-z]*b/g); // get all substrings starting with a and ending with b
let case2 = str.match(/b[a-z]*a/g); // get all substrings starting with b and ending with a
case1.forEach((matchedString) => {
if (matchedString.length == 5) {
return true;
}
});
case2.forEach((matchedString) => {
if (matchedString.length == 5) {
return true;
}
});
return false; // return false if no substrings matching condition exists
}
If you need to tell the difference between which case was triggered this could be a cleaner solution to read.
If you want to search for a pattern of 5 characters which starts and ends with (a and b) or (b and a) irrespective of case and any length of string, you can do something like this.
The regex considers that the string "a _ _ _ b" or "b _ _ _ a" can have only alphabets in any case not any other character, if you are accepting any other character you can update [a-zA-Z] part in the regex.
function findAB(str) {
const regexp = /(.?(((a|A)[a-zA-Z]{3}(b|B))|((b|B)[a-zA-Z]{3}(a|A))).?)/;
return regexp.test(str);
}
If it is fixed that length of string should be 5 and you are just dealing with first and last character you can simply use the following function
function findAB(str) {
const lengthOfString = str.length;
if (lengthOfString === 5) {
const firstCharacter = str[0].toLowerCase()
const lastCharacter = str[lengthOfString-1].toLowerCase()
return (firstCharacter === 'a' && lastCharacter === 'b') || (firstCharacter === 'b' && lastCharacter === 'a');
}
// returns false string does not contains 5 characters
return false;
}
Correcting your solution.
The problem with your solution is that indexOf returns -1 if the no match is found. So findAB("bbbbb") will return true, because indexOFa variable will be equal to -1 and lowerSTR[indexOFa + 4] will check the second last character and the condition will evaluate to true. So the following code will solve your problem.
function findAB(str) {
let lowerSTR = str.toLowerCase()
let indexOFa = lowerSTR.indexOf('a')
let indexOFb = lowerSTR.indexOf('b')
if ((indexOFa >= 0 && lowerSTR[indexOFa + 4] === 'b') || (indexOFb >= 0 && lowerSTR[indexOFb + 4] === 'a')) {
return true;
}
return false;
}
Also, I wouldn't prefer hardcoding 4 better use str.length-1.
You could also just simply do it like this
function findAB(str) {
let lowerSTR = str.toLowerCase();
let indexOFa = lowerSTR.indexOf('a');
let indexOFb = lowerSTR.indexOf('b');
if (
(indexOFa === 0 && indexOFb === str.length - 1) ||
(indexOFb === 0 && indexOFa === str.length - 1)
)
return true;
return false;
}

Best way to check if a character is a number of letter in javascript?

In javascript whats the best way to check if a character (length 1), is a number (i.e. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) or a letter (i.e. A to Z, a to z)?
Thanks
Why not:
function isNumber(i) {
return (i >= '0' && i <= '9');
}
function isLetter(i) {
return ((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z'));
}
I wrote a little test case for you, at least for the numeric checking function.
Considering the fact that all functions returns true with either a numberic 1 or a string '1' literal, using an Array seems to be the fastest way (at least in Chrome).
var isNumericChar = (function () {
var arr = Array.apply(null, Array(10)).map(function () { return true; });
return function (char) { return !!arr[char]; };
})();
However, if you accept that it might return false for 1, the switch statement is then significantly faster.
Try this.
function validate_string() {
var str = "a"; //change to desired value;
var regX = new RegExp("([0-9A-Za-z])");
var ans = false;
if(str.length == 1) {
ans = regX.test(str);
}
return ans;
}
Edit: Refactored my answer.
function validateString(char) {
let regx = new RegExp(/^[0-9A-Za-z]{1}$/g);
return regx.test(char);
}
validateString('4'); // true
validateString('as'); // false
validateString(''); // false
validateString(); // false
Maybe try something like this
var sum = 0; //some value
let num = parseInt(val); //or just Number.parseInt
if(!isNaN(num)) {
sum += num;
}
This blogpost sheds some more light on this check if a string is numeric in Javascript | Typescript & ES6
You can check for the type of the variable
function checkType(input){
console.log(typeof input)
}
checkType(1234); //number
checkType('Hello') //string
Here is an updated version
function checkType(i){
var input = i.toString(); //convert everything to strings to run .lenght() on it
for(var i=0; i<input.length; ++i){
if(input[i] >= '0' && input[i] <= '9'){
console.log(input[i]+' is a number');
}else if((input[i] >= 'a' && input[i] <= 'z') || (input[i] >= 'A' && input[i] <= 'Z')){
console.log(input[i]+' is a letter');
}
}
}
checkType('aa9fgg5')

Testing whether a value is odd or even

I decided to create simple isEven and isOdd function with a very simple algorithm:
function isEven(n) {
n = Number(n);
return n === 0 || !!(n && !(n%2));
}
function isOdd(n) {
return isEven(Number(n) + 1);
}
That is OK if n is with certain parameters, but fails for many scenarios. So I set out to create robust functions that deliver correct results for as many scenarios as I could, so that only integers within the limits of javascript numbers are tested, everything else returns false (including + and - infinity). Note that zero is even.
// Returns true if:
//
// n is an integer that is evenly divisible by 2
//
// Zero (+/-0) is even
// Returns false if n is not an integer, not even or NaN
// Guard against empty string
(function (global) {
function basicTests(n) {
// Deal with empty string
if (n === '')
return false;
// Convert n to Number (may set to NaN)
n = Number(n);
// Deal with NaN
if (isNaN(n))
return false;
// Deal with infinity -
if (n === Number.NEGATIVE_INFINITY || n === Number.POSITIVE_INFINITY)
return false;
// Return n as a number
return n;
}
function isEven(n) {
// Do basic tests
if (basicTests(n) === false)
return false;
// Convert to Number and proceed
n = Number(n);
// Return true/false
return n === 0 || !!(n && !(n%2));
}
global.isEven = isEven;
// Returns true if n is an integer and (n+1) is even
// Returns false if n is not an integer or (n+1) is not even
// Empty string evaluates to zero so returns false (zero is even)
function isOdd(n) {
// Do basic tests
if (basicTests(n) === false)
return false;
// Return true/false
return n === 0 || !!(n && (n%2));
}
global.isOdd = isOdd;
}(this));
Can anyone see any issues with the above? Is there a better (i.e. more accurate, faster or more concise without being obfuscated) version?
There are various posts relating to other languages, but I can't seem to find a definitive version for ECMAScript.
Use modulus:
function isEven(n) {
return n % 2 == 0;
}
function isOdd(n) {
return Math.abs(n % 2) == 1;
}
You can check that any value in Javascript can be coerced to a number with:
Number.isFinite(parseFloat(n))
This check should preferably be done outside the isEven and isOdd functions, so you don't have to duplicate error handling in both functions.
I prefer using a bit test:
if(i & 1)
{
// ODD
}
else
{
// EVEN
}
This tests whether the first bit is on which signifies an odd number.
How about the following? I only tested this in IE, but it was quite happy to handle strings representing numbers of any length, actual numbers that were integers or floats, and both functions returned false when passed a boolean, undefined, null, an array or an object. (Up to you whether you want to ignore leading or trailing blanks when a string is passed in - I've assumed they are not ignored and cause both functions to return false.)
function isEven(n) {
return /^-?\d*[02468]$/.test(n);
}
function isOdd(n) {
return /^-?\d*[13579]$/.test(n);
}
Note: there are also negative numbers.
function isOddInteger(n)
{
return isInteger(n) && (n % 2 !== 0);
}
where
function isInteger(n)
{
return n === parseInt(n, 10);
}
Why not just do this:
function oddOrEven(num){
if(num % 2 == 0)
return "even";
return "odd";
}
oddOrEven(num);
To complete Robert Brisita's bit test .
if ( ~i & 1 ) {
// Even
}
var isOdd = x => Boolean(x % 2);
var isEven = x => !isOdd(x);
var isEven = function(number) {
// Your code goes here!
if (number % 2 == 0){
return(true);
}
else{
return(false);
}
};
A few
x % 2 == 0; // Check if even
!(x & 1); // bitmask the value with 1 then invert.
((x >> 1) << 1) == x; // divide value by 2 then multiply again and check against original value
~x&1; // flip the bits and bitmask
We just need one line of code for this!
Here a newer and alternative way to do this, using the new ES6 syntax for JS functions, and the one-line syntax for the if-else statement call:
const isEven = num => ((num % 2) == 0);
alert(isEven(8)); //true
alert(isEven(9)); //false
alert(isEven(-8)); //true
A simple modification/improvement of Steve Mayne answer!
function isEvenOrOdd(n){
if(n === parseFloat(n)){
return isNumber(n) && (n % 2 == 0);
}
return false;
}
Note: Returns false if invalid!
Different way:
var isEven = function(number) {
// Your code goes here!
if (((number/2) - Math.floor(number/2)) === 0) {return true;} else {return false;};
};
isEven(69)
Otherway using strings because why not
function isEven(__num){
return String(__num/2).indexOf('.') === -1;
}
if (testNum == 0);
else if (testNum % 2 == 0);
else if ((testNum % 2) != 0 );
Maybe this?
if(ourNumber % 2 !== 0)
var num = someNumber
isEven;
parseInt(num/2) === num/2 ? isEven = true : isEven = false;
for(var a=0; a<=20;a++){
if(a%2!==0){
console.log("Odd number "+a);
}
}
for(var b=0; b<=20;a++){
if(b%2===0){
console.log("Even number "+b);
}
}
Check if number is even in a line of code:
var iseven=(_)=>_%2==0
This one is more simple!
var num = 3 //instead get your value here
var aa = ["Even", "Odd"];
alert(aa[num % 2]);
To test whether or not you have a odd or even number, this also works.
const comapare = x => integer(checkNumber(x));
function checkNumber (x) {
if (x % 2 == 0) {
return true;
}
else if (x % 2 != 0) {
return false;
}
}
function integer (x) {
if (x) {
console.log('even');
}
else {
console.log('odd');
}
}
Using modern javascript style:
const NUMBERS = "nul one two three four five six seven ocho nueve".split(" ")
const isOdd = n=> NUMBERS[n % 10].indexOf("e")!=-1
const isEven = n=> isOdd(+n+1)
function isEven(n) {return parseInt(n)%2===0?true:parseInt(n)===0?true:false}
when 0/even wanted but
isEven(0) //true
isEven(1) //false
isEven(2) //true
isEven(142856) //true
isEven(142856.142857)//true
isEven(142857.1457)//false
​
if (i % 2) {
return odd numbers
}
if (i % 2 - 1) {
return even numbers
}

Categories

Resources