Javascript Palindrome Check - javascript

I have to write a script to check if a word entered by a user is a Palindrome. I've gotten as far as validating the word and displaying the number of characters. Also not supposed to use the reverse method.
I've looked at some of the examples here and think I need to turn the user input into a string and use a "for" loop and if/else statement. But how do I turn the user input into a string in order to check each character? This is a total mess but it's all I've got so far:
function checkWord(userWord3) {
var answer = "Your word is";
answer += retrieveWord(userWord3);
return (answer);
}
function retrieveWord(userWord) {
var string = userWord;
var i = userWord.length;
for(var i = 0; i < str.length / 2; i++) {
alert(str[i], str[str.length -i -1]);
if( str[i] != str[str.length - i -1] ) {
return false;
}
}
}

You can try this function
function isPalindrome(str){
if(str.length < 2) return true;
if(str[0] != str.slice(-1)) return false;
return isPalindrome(str.slice(1,-1));
}
It uses recursion and its logic is as follows
The empty and 1 character string are considered palindromes
if(str.length == 0 || str.length == 1) return true;
if the first and last characters are not the same the word is not a palindrome
if(str[0] != str.slice(-1)) return false;
if the first and last are the same continue searching in the remaining string
return isPalindrome(str.slice(1,-1));
var result = document.querySelector(".result");
var palindrome = "<span class='palindrome'>it is a palindrome</span>";
var notpalindrome = "<span class='notpalindrome'>it is NOT a palindrome</span>";
function isPalindrome(str){
if(str.length == 0 || str.length == 1) return true;
if(str[0] != str.slice(-1)) return false;
return isPalindrome(str.slice(1,-1));
}
document.querySelector("input").addEventListener("keyup", function(){
if(isPalindrome(this.value)){
result.innerHTML = palindrome;
} else {
result.innerHTML = notpalindrome;
}
})
.palindrome{color: green;}
.notpalindrome{color: red;}
<input type="text" />
<span class="result"></span>

How are you collecting the user input? In just about every case, it will come into the program as a string (i.e. textbox, prompt), so you don't have to worry about converting it into one.
This code simply takes the word, breaks it into an array, reverses the array and then compares that reversal against the original word. It works for me:
function test(input){
var originalData = input;
var a = [];
for(var i = 0; i < input.length; ++i){
a.push(input.charAt(i));
}
a.reverse();
return (a.join('') === originalData) ? true : false;
}
var word = document.getElementById("userWord");
alert(test(word));
See working version at: https://jsfiddle.net/6cett0bc/6/

The most basic version I can think of is to split the word into letters and check the first against the last, until you end up in the middle, where it doesn't matter if there is an odd amount of letters.
UPDATE I've tested the performance of various implementations and changed my array based answer to a pure string based solution.
If you're curious, here are the performance benchmarks
The fastest solution (so far):
function palindrome(word) {
var middle = Math.ceil(word.length / 2), // determine the middle
i; // prepare the iteration variable
// loop from 0 to middle
for (i = 0; i <= middle; ++i) {
// check letter i against it counterpart on the opposite side
// of the word
if (word[i] !== word[(word.length - 1) - i]) {
// it is not a palindrom
return false;
}
}
// otherwise it is
return true;
}
// listen for clicks on the button and send the entered value to the palindrom function
document.querySelector('button').addEventListener('click', function(e) {
// obtain the input element
var element = document.querySelector('input');
// add/remove the 'palindrom' CSS class to the input field, depending on
// the output of palindrome function
if (palindrome(element.value)) {
element.classList.add('palindrome');
}
else {
element.classList.remove('palindrome');
}
});
input {
color: red;
}
input.palindrome {
color: green;
}
<input name=check placeholder=palindrome><button>check</button>
The text turns green if you have entered a palindrome successfully, red (default) otherwise.

Related

Js function that returns a matching letter from 2 strings

Function that returns the first letter that is present in both strings that a user submits via
an input type text, the strings are separated with a comma. For example:aaaaa,bbbbba--> the matching letter is 'a'because is present in both strings
Sorry for some italian names but i code in italian
I'm not sure how to continue, i have a for to go throught both strings, but i'm not sure if it's correct
function Ripetizione() {
var rip = document.getElementById("string").value;
if (rip.indexOf(",") == -1) { //check to see if the comma is not present
alert("Non c'è nessuna virgola");
return;
}
var stringa1 = rip.substr(0, rip.indexOf(",")); //this is the string1 before the comma
var stringa2 = rip.substr(rip.indexOf(",") + 1, rip.length - (stringa1.length + 1)); //this is the second string after the comma
for (i = 0; i <= stringa1.length; i++) { //for cycle to count the elements of the first string
}
for (k = 0; i <= stringa2.lenght; k++) { //same for the string2
}
}
Ripetizione()
You need not loop the second string.. Just check for index of the element => 0 , while looping through each element of first string part. And return the value..
Always prefer functional over imperative programming.Use Array#find
function getCommonLetter(str){
const [stringA, stringB]=str.split(',');
return Array.from(stringB).find(val => stringA.includes(val));
}
console.log(getCommonLetter('ab,ba'))
console.log(getCommonLetter('ads,bsd'))
console.log(getCommonLetter('aaa,bbc'))
function Ripetizione() {
var rip=document.getElementById("string").value;
if (rip.indexOf(",")==-1){
alert("Non c'è nessuna virgola");
return;
}
var stringa1=rip.substr(0,rip.indexOf(","));
var stringa2=rip.substr(rip.indexOf(",")+1,rip.length-(stringa1.length+1));
return search(stringa1, stringa2);
}
function search(a, b){
for(var i=0; i<a.length;i++){
for(var j=0;j<b.length;j++){
if(a[i] == b[j]){
return a[i];
}
}
}
}
We can do it using Array#reduce and check for the presence of the matching chars using Array#includes.
The idea is to convert the strings into an array of string using Array#from then use the reduce function to match and accumulate the matched characters.
//returns the matching chars as an array
function Ripetizione(rip) {
//let rip=document.getElementById("string").value;
let strs = rip.split(",");
if (strs.length !== 2){ //check to see if the comma is not present
alert("Non c'è nessuna virgola");
return;
}
//converting strings to array to use reduce
let strOne = Array.from(strs[0]), strTwo = strs[1];
return strOne.reduce((acc,alpha)=> {
return !acc.includes(alpha) && strTwo.includes(alpha)?[alpha,...acc]:acc;
},[]).slice(0,1).toString();
}
console.log(Ripetizione("aaaaaab,bbbbba"));
console.log(Ripetizione("aaaaaa,bbbbba"));
console.log(Ripetizione("acccaaaa,bbbbba"));
console.log(Ripetizione("acccaaaa,bbbbcba"));
console.log(Ripetizione("dddddddd,bbbbba")); //return blank string
console.log(Ripetizione("ab,ba"));
function Ripetizione() {
var rip = document.getElementById("string").value;
if (rip.indexOf(",") == -1) { //check to see if the comma is not present
alert("Non c'è nessuna virgola");
return;
}
var stringa1 = rip.substr(0, rip.indexOf(",")); //this is the string1 before the comma
var stringa2 = rip.substr(rip.indexOf(",") + 1, rip.length - (stringa1.length + 1)); //this is the second string after the comma
if (stringa1.length <= stringa2.length) {
stringa2 = stringa2.split('')
stringa1 = stringa1.split('')
for (i = 0; i <= stringa2.length; i++) { //for cycle to count the elements of the first string
if (stringa1.includes(stringa2[i])) {
console.log(stringa2[i]);
}
}
} else if (stringa1.length >= stringa2.length) {
stringa1 = stringa1.split('')
stringa2 = stringa2.split('')
for (i = 0; i <= stringa1.length; i++) { //for cycle to count the elements of the first string
if (stringa2.includes(stringa1[i])) {
console.log(stringa1[i]);
}
}
}
}
<input id="string" type="text">
|<button id="ok" onclick="Ripetizione()">done</button>
The following demo binds the change event to input. When a user enters text in input then clicks outside of input the function is called. The function uses split() and filter() and displays the result in an output. The function also removes any spaces and reports if there are no matches as well.
Demo
Details are commented in demo
var str = document.getElementById("string");
// This is an Event Handler
function ripZ(e) {
var result = document.getElementById('result');
var rip = this.value;
if (rip.indexOf(",") === -1) {
result.value = "Separate the two strings with a comma (no spaces).";
return;
}
// If there's a space remove it
var rip = rip.replace(/\s/g, '');
// Split the string at the comma making an array of two strings
var array = rip.split(',');
/*
Take each string and split them at each letter.
Now there's two arrays of letters
*/
var first = array[0].split('');
var second = array[1].split('');
/*
Loop through both arrays by using two for...of loops
*/
var match = first.filter(function(f, i) {
return second.indexOf(f) !== -1;
});
// Display results
if (match) {
result.innerHTML = `
The letter "${match[0]}" is the first match between both strings.`;
} else {
result.value = "There was no match."
}
return;
}
/*
This is an onevent property registered to the input
If a user types into the input then clicks outside of input
the Event Handler ripZ() is called.
*/
str.onchange = ripZ;
<input id='string'><button>GO</button><br>
<output id='result'></output>
If the input was "ab,ba", you sad that it should be return b so Code must be above in my openion :
function Ripetizione() {
// var rip=document.getElementById("string").value;
// if (rip.indexOf(",")==-1){
// alert("Non c'è nessuna virgola");
// return;
// }
// var stringa1=rip.substr(0,rip.indexOf(","));
// var stringa2=rip.substr(rip.indexOf(",")+1,rip.length-(stringa1.length+1));
var stringa1="ab";
var stringa2="ba";
for(var i=0; i<stringa2.length;i++){
for(var j=0;j<stringa1.length;j++){
if(stringa2.charAt(i) === stringa1.charAt(j)){
console.log(stringa2.charAt(i));
return;
}
}
}

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;
}

How to check whether word within array is included in string, without regex?

I’m trying to figure out why my code is not giving the right output.
My input shouldn’t be contained within the array elements.
I found an easy way to solve it with regex, so I am not using regex for that one.
Please, break down my code, and tell me what is the problem with the code.
function checkInput(input, words) {
var arr = input.toLowerCase().split(" ");
var i, j;
var matches = 0;
for (i = 0; i < arr.length; i++) {
for (j = 0; j < words.length; j++) {
if (arr[i] != words[j]) {
matches++;
}
}
}
if (matches > 0) {
return true;
} else {
return false;
}
};
console.log(checkInput("Move an array element from one array", ["from"])); // should be false
console.log(checkInput("Move an array element from one array", ["elem"])); // should be true
if (arr[i] != words[j]) will be true at some point or another most of the time.
You want to check the opposite and return the opposite logic, so:
if(arr[i] == words[j]) {
matches++;
}
and
if (matches > 0) {
return false;
} else {
return true;
}
But a simpler way would be:
function checkInput(input, words){
let lowerCaseInput = input.toLowerCase().split(" ");
return words.find(word => lowerCaseInput.includes(word)) === undefined;
}
Array.prototype.find will return undefined iff no element is found that satisfies a specific rule provided by the callback function, word => lowerCaseInput.includes(word) in this case. So we check whether its return value is undefined which will tell us whether a word has been matched in input.
Note that your function unnecessarily checks for the entire words array even though it only matters whether one word matches.
Also, the words in words are case-sensitive! If you don’t want that, replace .includes(word) by .includes(word.toLowerCase()).
Because you are using matches > 0, you think it will return true only when no matches is found. But what happens is that when you have input ab aa cc and word aa
first iteration matches = 1
second iteration matches = 1
third iteration matches = 2
So matches will contain how many times word is different from items of input. So as result, it will always return true as long as input is more than two words long, for at least one word of input will be different from word. You can rather consider increasing the value of matches if word is found instead.
function checkInput(input, words) {
var arr = input.toLowerCase().split(" ");
var i, j;
var matches = 0;
for (i = 0; i < arr.length; i++) {
for (j = 0; j < words.length; j++) {
if (arr[i] === words[j]) {
matches++;
}
}
}
if (matches === 0) {
return true;
} else {
return false;
}
};
console.log(checkInput("Move an array element from one array", ["from"]));
console.log(checkInput("Move an array element from one array", ["elem"]));

JS function to validate input name not working correctly

The objective of this code is to check the name the user inputs. If the value contains something other than -abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ the function will throw an error.
I am unable to get this to work, and I'm not allowed to use Regular expressions. I've also tried String1.indexOf(usr.substr(i,1)) > -1) but that doesn't seem to work neither.
function nameValidation(username) {
var usr = document.getElementById("username").value;
usr = usr.trim();
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var ok = 1;
for (var i = 0; i < usr.length; i++) {
if (!isNaN(usr[i])) {
ok = 0;
break;
} else {
ok = 1;
document.getElementById("fnerror").innerHTML = "";
document.getElementById("username").style.borderColor = "lightgrey";
return true;
}
}
if (ok == 0) {
document.getElementById("fnerror").innerHTML = "X Enter Upper and lower case letters, hypen, apostrohe only please";
return false;
}
return true;
}
Something like this, maybe:
function isValidUsername(username) {
var alpha = "-'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
username = username.toUpperCase();
for (var i = 0, l = username.length; i < l; i++) {
if (alpha.indexOf(username[i]) === -1) return false;
}
return true;
}
Cheaper to upper-case the string and therefore have a shorter set of characters to test against (though probably marginal at best because there's a cost to even native-uppercasing..)
You can do it in a more "functional way", by using every method, which allow us to break a loop instead of foreach.
The every method executes the provided callback function once for each element present in the array until it finds one where callback returns a falsy value (a value that becomes false when converted to a Boolean). If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
Array.proototype.every
So :
function check(){
//Get value input and transform it into array
var value = document.querySelector('#username').value.split('');
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//If there is an error, stop the loop and return result
return value.every(function(elm){
//check if elm is an alpha string
return alpha.indexOf(elm) > -1;
});
}
The easiest (to understand at least) solution (that doesn't use regex), would be to loop through your string character by character and check .indexOf against your list of allowed characters, something like:
for (var i = 0; i < input.length; i++) {
if (alpha.indexOf(input[i])==-1) {
console.log("ERROR");
break;
}
}
EDITED: I read the question wrong and thought you wanted to return true if there's a letter. It will now make sure that each character is within the ASCII values of A and z.
text = "ABCDEFzzxasd1";
valid = true;
for( i = 0; i < text.length; i++ ) {
if ( text.charCodeAt(i) < 65 || text.charCodeAt(i) > 122 ) {
alert("Woah, that's not a letter!");
valid = false;
break;
}
}
Begin with
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('');
function duplicates( element, index, array ){
return array.indexOf(element) == index;
}
function isNameFormatCorrect( userName ){
return ( alpha.concat(username.split(''))
.filter( duplicates ).length === alpha.length );
}
Then
var username = "YourUserNameHere-"
isNameFormatCorrect( username ); => true;
var username = "YourUserNameHere-**"
isNameFormatCorrect( username ); => false;

javascript check if value has at least 2 or more words

I have a field that you enter your name in and submit it. I would like the receive peoples first and last names and to do this i need to check if the value contains at least 2 words. This is what I am using right now but it doesn't seem to work.
function validateNameNumber(name) {
var NAME = name.value;
var matches = NAME.match(/\b[^\d\s]+\b/g);
if (matches && matches.length >= 2) {
//two or more words
return true;
} else {
//not enough words
return false;
}
}
str.trim().indexOf(' ') != -1 //there is at least one space, excluding leading and training spaces
The easy solution (not 100% reliable, since "foo " returns 4, as #cookiemonster mentioned):
var str = "Big Brother";
if (str.split(" ").length > 1) {
// at least 2 strings
}
The better solution:
var str = "Big Brother";
var regexp = /[a-zA-Z]+\s+[a-zA-Z]+/g;
if (regexp.test(str)) {
// at least 2 words consisting of letters
}
You could use the String.Split() method:
function validateNameNumber(name) {
var NAME = name.value;
var values = name.split(' ').filter(function(v){return v!==''});
if (values.length > 1) {
//two or more words
return true;
} else {
//not enough words
return false;
}
}
If you were to pass "John Doe" as the name value, values would equal {"john", "doe"}
http://www.w3schools.com/jsref/jsref_split.asp
Edit: Added filter to remove empty values. Source: remove an empty string from array of strings - JQuery
Probably not the best solution overall (see the other answers), but one that shows how to count the number of times a regexp matches a string:
function validateNameNumber(name) {
var nameValue = name.value;
var regexp = /\b[^\d\s]+\b/g;
var count = 0;
while (regexp.exec(nameValue)) ++count;
if (count >= 2) {
//two or more words
return true;
} else {
//not enough words
return false;
}
}
Change this line from your snippet
var matches = NAME.match(/\b[^\d\s]+\b/g);
to this
var matches = NAME.match(/\S+/g);
or to this, if numbers should be excluded
var matches = NAME.match(/\b([a-z]+)\b/gi);
Side (funny) note: Your snippet works just fine. Check the jsBin
I would just check for whitespace by running a for loop.
var correctFormat = false;
for (var i = 0; i = i < name.length; i++) {
if (name[i] === " ") {
correctFormat = true;
}
}
if (correctFormat === false) {
alert("You entered an invalid name");
return false;
} else {
return true;
}
If the name doesn't have a space, knowing that there is a space between the first and last name, it would alert("You entered an invalid name");

Categories

Resources