So I am trying to create a code for palindrome this is how I tried. Is there another or better way of doing it?
But now it only shows that if the first value is equal or not and shows true or false?
var inpo= prompt("Please enter to check if palindrome")
var inp = parseFloat(inpo)
var a = inpo.split('')
var inpo2 = a.reverse()
var len= inpo.length
for (var i =0;i< len ;i++) {
if (inpo[i] == inpo2[i] )
alert("True")
else
alert("False")
}
A way to check if a word or an entire phrase is a palindrome or not:
function isPalindrome(str) {
// Escape the string: Eliminate punctuation and spaces, enforce lower case
let escaped = str.replace(/[^A-Za-z0-9_]/g,"").toLowerCase();
// Reverse the escaped string
let reversed = escaped.split('').reverse().join('');
//compare
return escaped == reversed;
}
console.log(isPalindrome('Level'));
console.log(isPalindrome('Red rum, sir, is murder'));
I hope the comments serve well as an explanation.
Also, you have a prompt example in THIS jsfiddle.
If you are creating a palindrome checker code, here is a simple way to do it. Split, reverse then join.
str1 = "xxaa";
str2 = str1.split('').reverse().join("");
if (str1 == str2) {
alert("good");
} else {
alert("not");
}
You can check the single character from the string consuming 1 character from right and another from left until you will find either the string is finished or there are 2 inequal character. I implemented with a classical for loop.
Note that bracket notation for strings [] is only recently supported, you can use charAt if memory serves me right
let inp = "otdto";
console.log(isPalindrome(inp));
function isPalindrome(inp) {
const len = inp.length;
for (let i = 0; i < Math.floor(len / 2); i++)
if (inp[i] != inp[len - i - 1])
return false;
return true;
}
Related
I am doing doing a few code challenges in the hope to learn some new stuff. Currently I have written a piece of code that find charachter of a given word in a string of random letters.
I thought regexp might be the best performance-wise (it's one of the objectives). This code passes the checks but takes too long with absurd long strings. Is there any way I can improve this? It's really ugly as is honestly. I've tried several approaches but I am probably just really a newbie at reg exp etc.
before all the if statements I only used regexp but if str2 which is the word I am looking for had double characters it would come back 'true' because it would count already counted characters. That is why I am using replace to exclude them. That's all I could get.
the goal is to return true if a portion of str1 can be rearranged to form str2, otherwise return false. Only lower case letters will be used (a-z). No punctuation or digits will be included. for example scramble('aabbcamaomsccdd','commas') should return true
function scramble (str1, str2)
{
var o = 0; // tracks amount of matched letters.
for(i = 0; i < str2.length; i++)
{
var regex1 = new RegExp (str2[i]) ; // select letter from word that needs to be found
if( regex1.test(str1) == true)// if selected character is found us replace to remove it from the random characters string for next iteration.
{
str1 = str1.replace(regex1 ,"");
o++; // increment o if character is removed from random string.
}
}
//check if amount of removed characters equals total characters of word that we want.
if ( o == str2.length)
{
return true
}
if (o !== str2.length)
{
return false
}
}
Update: I flagged the hash table as answer because afaik this was not doable with regexp it seems also I was able to achieve a proper result with .split and loops myself plus the hash table also achieved this.
if-less methodology!
i didnt stress it on tests but looks fine
function scramble(str1, str2) {
str1 = [...str1];
return [...str2].filter((str => (str == str1.splice(str1.indexOf(str), 1)))).join('') == str2;
}
You could take a hash table, count the wanted characters and return if no count is not more necessary.
function scramble (str1, str2) {
var counter = {},
keys = 0;
for (let i = 0; i < str2.length; i++) {
if (!counter[str2[i]]) {
counter[str2[i]] = 0;
keys++;
}
counter[str2[i]]++;
}
for (let i = 0; i < str1.length; i++) {
if (!counter[str1[i]]) continue;
if (!--counter[str1[i]] && !--keys) return true;
}
return false;
}
console.log(scramble('abc', 'cba'));
console.log(scramble('abc', 'aba'));
console.log(scramble('abcdea', 'aba'));
console.log(scramble('aabbcamaomsccdd', 'commas'));
Input = ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))
Expected Output = ABCDEF,GHIJKLMN,OPQRSTUVW
Tried so far
Output = Input.replace(/ *\([^)]*\)*/g, "");
Using a regex here probably won't work, or scale, because you expect nested parentheses in your input string. Regex works well when there is a known and fixed structure to the input. Instead, I would recommend that you approach this using a parser. In the code below, I iterate over the input string, one character at at time, and I use a counter to keep track of how many open parentheses there are. If we are inside a parenthesis term, then we don't record those characters. I also have one simple replacement at the end to remove whitespace, which is an additional step which your output implies, but you never explicitly mentioned.
var pCount = 0;
var Input = "ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))";
var Output = "";
for (var i=0; i < Input.length; i++) {
if (Input[i] === '(') {
pCount++;
}
else if (Input[i] === ')') {
pCount--;
}
else if (pCount == 0) {
Output += Input[i];
}
}
Output = Output.replace(/ /g,'');
console.log(Output);
If you need to remove nested parentheses, you may use a trick from Remove Nested Patterns with One Line of JavaScript.
var Input = "ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))";
var Output = Input;
while (Output != (Output = Output.replace(/\s*\([^()]*\)/g, "")));
console.log(Output);
Or, you could use a recursive function:
function remove_nested_parens(s) {
let new_s = s.replace(/\s*\([^()]*\)/g, "");
return new_s == s ? s : remove_nested_parens(new_s);
}
console.log(remove_nested_parens("ABCDEF ((3) abcdef),GHIJKLMN ((4)(5) Value),OPQRSTUVW((4(5)) Value (3))"));
Here, \s*\([^()]*\) matches 0+ whitespaces, (, 0+ chars other than ( and ) and then a ), and the replace operation is repeated until the string does not change.
The task at hand;
Return true if the string in the first element of the array contains
all of the letters of the string in the second element of the array.
For example, ['hello', 'Hello'], should return true because all of the
letters in the second string are present in the first, ignoring case.
The arguments ['hello', 'hey'] should return false because the string
'hello' does not contain a 'y'.
Lastly, ['Alien', 'line'], should return true because all of the
letters in 'line' are present in 'Alien'.
My attempted solution that isn't working;
function mutation(arr) {
if (arr[0].toLowerCase().indexOf(arr[1].toLowerCase()) >= 0){
return true;
}else{
return false;
}
return arr;
}
mutation(['hello', 'hey']);
Can someone please explain to me why it isn't working. I am not looking for an answer just an explanation so that I can understand better.
Many thanks
Try this:
$('#id').click(function() {
var arr = ['hello','hey'];
var isExist = false;
for (i = 0;i < arr[1].length; i++) {
if(arr[0].toLowerCase().indexOf(arr[1][i].toLowerCase()) >= 0)
isExist = true;
else {
isExist = false;
break;
}
}
if (isExist)
alert('true'); // In case of all chars of 2nd present in 1st arr
});
what you are doing is that, you are converting first element to lower case and than trying to find the second element in first array.
your solution will work for the cases where the whole second element exists in first element as a sub string or both elements are exactly same.
for example it'll work for following examples
['hello', 'Hello']
['hello', 'ell']
['hello', 'He']
But it will not work when letters in second string are shuffled first string. for following examples your solution will fail.
['Alien', 'line']
['hello', 'elo']
['hello', 'Hol']
If whole second word does not exists as it is in first word your solution will not work.
Let me know if this is helpful. i'll provide you the solution if you need.
As another answer correctly states, your code does not work because it's looking in the first string for the second string, in its entirety, with the letters in the same order. Instead, you need to look at each letter in the second string individually and check that it's in the first string.
We'll adopt the strategy of "Programming in English and going backward". The English for the overall problem is:
Does every letter to check match?
We can write this in JavaScript as
letters_to_check . every(matches)
We can calculate letters_to_check as input[1].toLowerCase().split('').
Now we have to write the matches function, which can be expressed in English as
Is the letter found in the string to check against?
So we write
function matches(letter) { return string_to_heck_against.search(letter); }
string_to_check_against is of course input[0].
The entire program is thus:
function mutation(input) {
// Check if a letter is in the string to be checked against.
function matches(letter) { return string_to_check_against.search(letter); }
var string_to_check_against = input[0].toLowerCase();
var string_to_check = input[1].toLowerCase();
var letters_to_check = string_to_check.split('');
return letters_to_check . every(matches);
}
If you are programming in ES6, this could be written as
function mutation([source, target]) {
return target .
toLowerCase() .
split('') .
every(letter => source.toLowerCase().search(letter));
}
According to your output you have to check all the characters of array second string with array first string. For this you have to check all characters are available or not in the first string, not using the direct string. If we use strings directly, it will look for total string not for the characters.
Try the following:
var arr = ['Alien', 'line'];
var arr1 = ['hello','hey'];
var arr2 = ['hello','Hello'];
function mutation(arr) {
var str1 = arr[0].toLowerCase();
var str2 = arr[1].toLowerCase();
var o = false;
for (var i=0;i<str2.length;i++) {
o = (str1.indexOf(str2[i]) !== -1);
if (!o) break;
}
return o;
}
console.log('first arr : ', mutation(arr));
console.log('second arr :', mutation(arr1));
console.log('third arr :', mutation(arr2));
This is my working code. You can check. The idea is to transfer both strings in the array to lowercase. Then we compare both strings together.
I take every single letter from the shorter string, then use the indexOf function to check if it's in the longer string. Every time there is a match, the valule no1 or no2 will increase.
If the value of no1 or no2 equal with the length of the shorter string, it means all the letters in the shorter string is inside the longer string.
function mutation(arr) {
// transfer both strings in the array to lower case
var val1 = arr[0].toLowerCase();
var val2 = arr[1].toLowerCase();
// check if val2 is shorter than val1
if(val1.length >= val2.length){
var no1 = 0;
// Check every if any letter in val2 is in val1
for(var i = 0; i < val2.length; i++){
if(val1.indexOf(val2[i]) != -1){
// plus 1 if there is a match
no1++;
}
}
// check if the value of no1 equals to length of val2
if(no1 == val2.length){
return true;
}else{
return false;
}
}else if(val2.length > val1.length){
var no2 = 0;
for(var j = 0; j < val1.length; j++){
if(val2.indexOf(val1[j]) != -1){
no2++;
}
}
if(no2 == val1.length){
return true;
}else{
return false;
}
}
}
I'm attempting to answer this question:
Using the JavaScript language, have the function SimpleSymbols(str) take the str parameter being passed and determine if it is an acceptable sequence by either returning the string true or false. The str parameter will be composed of + and = symbols with several letters between them (ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter.
Here's my solution:
function SimpleSymbols(str) {
var test;
for (var i =0; i<str.length; i++){
if ((str.charAt(i)!== '+' && str.charAt(i+1) === str.match(/[a-z]/))
||(str.charAt(i+1) === str.match(/[a-z]/) && str.charAt(i+2) !== '+')){
test = false;
break;
}
else if (str.charAt(0) === str.match(/[a-z]/)){
test = false;
break;}
else {
test= true;}
}
return test;
};
I think you can just use two regex and then compare the length of arrays returned by them
function SimpleSymbols(str){
return str.match(/[a-z]/g).length == str.match(/\+[a-z]\+/g).length;
}
The first regex /[a-z]/g will match all the letters and /\+[a-z]\+/g will match all the letters which are followed and preceded by a literal +.
Then, we just use the Array.length property to check if the lengths are same or not and then return the Boolean result. As simple as that.
Am trying to find some text only if it contains english letters and numbers using Javascript/jQuery.
Am wondering what is the most efficient way to do this? Since there could be thousands of words, it should be as fast as possible and I don't want to use regex.
var names[0] = 'test';
var names[1] = 'हिन';
var names[2] = 'لعربية';
for (i=0;i<names.length;i++) {
if (names[i] == ENGLISHMATCHCODEHERE) {
// do something here
}
}
Thank you for your time.
A regular expression for this might be:
var english = /^[A-Za-z0-9]*$/;
Now, I don't know whether you'll want to include spaces and stuff like that; the regular expression could be expanded. You'd use it like this:
if (english.test(names[i])) // ...
Also see this: Regular expression to match non-English characters?
edit my brain filtered out the "I don't want to use a regex" because it failed the "isSilly()" test. You could always check the character code of each letter in the word, but that's going to be slower (maybe much slower) than letting the regex matcher work. The built-in regular expression engine is really fast.
When you're worried about performance, always do some simple tests first before making assumptions about the technology (unless you've got intimate knowledge of the technology already).
If you're dead set against using regexes, you could do something like this:
// Whatever valid characters you want here
var ENGLISH = {};
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("").forEach(function(ch) {
ENGLISH[ch] = true;
});
function stringIsEnglish(str) {
var index;
for (index = str.length - 1; index >= 0; --index) {
if (!ENGLISH[str.substring(index, index + 1)]) {
return false;
}
}
return true;
}
Live Example:
// Whatever valid characters you want here
var ENGLISH = {};
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("").forEach(function(ch) {
ENGLISH[ch] = true;
});
function stringIsEnglish(str) {
var index;
for (index = str.length - 1; index >= 0; --index) {
if (!ENGLISH[str.substring(index, index + 1)]) {
return false;
}
}
return true;
}
console.log("valid", stringIsEnglish("valid"));
console.log("invalid", stringIsEnglish("invalid!"));
...but a regex (/^[a-z0-9]*$/i.test(str)) would almost certainly be faster. It is in this synthetic benchmark, but those are often unreliable.
Iterate each character in the string and check if the key code is not between 65 and 122, which are the Latin alphabet, lowercase and uppercase.
If wished to add punctuations characters, add their keyCode to the check.
function isLatinString(s) {
var i, charCode;
for (i = s.length; i--;) {
charCode = s.charCodeAt(i)
if (charCode < 65 || charCode > 122)
return charCode
}
return true
}
// tests
[
"abxSDSzfgr",
"aAzZ123dsfsdfעחלעלחי",
"abc!",
"$abc",
"123abc",
" abc"
]
.forEach(s => console.log( isLatinString(s), s ))
Another way, using an explicit whitelist string to allow specific charatcers:
function isLatinString(s){
var c, whietlist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for( c in s ) // get each character in the argument string
// if whitelist string doesn't include the character, break
if( !whietlist.includes(s[c].toUpperCase()) )
return false
return true
}
// tests
[
"abCD",
"aAאב",
"abc!",
"$abc",
"1abc",
" abc"
]
.forEach(s => console.log( isLatinString(s), s ))
Using regex is the fastest way to do this I'm afraid. This to my knowledge should be the fastest algorithm:
var names = 'test',
var names[1] = 'हिन';
var names[2] = 'لعربية';
//algorithm follows
var r = /^[a-zA-Z0-9]+$/,
i = names.length;
while (--i) {
if (r.test(names[i])) {
// do something here
}
}
You should consider words that may contain special characters. For example {it's}, isn't it english?