If we had our input as "1125" and the maximum value as 26 for example, then our output would be:
[ [1,1,2,5] , [11,2,5] , [1,12,5] , [1,1,25] , [11,25] ]
that's an array that consists of every possible way to separate the characters to be less than the value 26.
We can use this to decrypt messages that have been converted letters into alphabetical numbers but without delimiters.
Here's my current code that's my first try to solve this:
Array.prototype.indexOfArray=function(array){
for(var i=0;i<this.length;i++){
if(this[i].length==array.length){
var same=true;
for(var j=0;j<this[i].length;j++){
if(this[i][j]!=array[j]){
same=false;
break;
}
}
if(same){
return i;
}
}
}
return-1;
};
function possibilities(string,max){ //The function I'm talking about.
var output=[];
(function collector(array,held,start){
for(var i=start;i<string.length;i++){
var char=string[i];
if(Number(held+char)>max){
array.push(held);
held=char;
}else{
held+=char;
if(i!=string.length-1){
collector(array.slice().concat(held),"",i+1);
}
}
}
if(held.length>0){
array.push(held);
}
if(output.indexOfArray(array)==-1){
output.push(array);
}
})([],"",0);
return output;
}
var message="302213"; //"dawn" is "3 0 22 13" with delimiters
var alphabet="abcdefghijklmnopqrstuvwxyz";
var solutions=possibilities(message,alphabet.length);
for(var i=0;i<solutions.length;i++){
console.log(solutions[i].join(",")+" : "+solutions[i].map(x=>alphabet[Number(x)]).join(""));
}
And prints out:
3,0,2,2,1,3 : daccbd
3,0,2,2,13 : daccn
3,0,2,21,3 : dacvd
3,0,22,1,3 : dawbd
3,0,22,13 : dawn
3,02,2,1,3 : dccbd
3,02,2,13 : dccn
3,02,21,3 : dcvd
3,022,1,3 : dwbd
3,022,13 : dwn
How could I improve this? What's the name of this algorithm?
You could use a different approch for glueing parts together, with 2array.length - 1 as formular for different chunked parts. Then filter the ones out, which have a value greater than 25.
function split(string) {
var array = string.split(''),
result = [],
i, l = 1 << (array.length - 1),
v, j,
temp;
for (i = 0; i < l; i++) {
v = i;
temp = [array[0]];
for (j = 1; j < array.length; j++) {
if (v & 1) {
temp[temp.length - 1] += array[j];
} else {
temp.push(array[j]);
}
v = v >> 1;
}
result.push(temp);
}
return result.filter(function (a) {
return a.every(function (b) {
return b < 26;
});
});
}
function output(array) {
array.forEach(function (a) {
console.log(a.join(), a.map(function (b) { return (+b + 10).toString(36); }).join(''));
});
}
output(split('302213'));
output(split('1125'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
this is nice example for recursive approach. Let us do some definitions first
Input
Input lowercase string <'a','z'> is encoded to <1,26> without delimiters.
output
we want to obtain all decoding of string combinations for each valid decoding 1 vs. 2 digit codes.
Heuristics
so 2 digit codes can start with { 1,2 } and { 0 } means that we are handlin 2 digit code { 10,20 } or { 0 } for <0,25> this can be used to lower the combinations number.
Recursive algorithm
if we have some function like decode(in); then we can recursively do this in simple manner like this:
decode (string in)
{
l=in.Length();
add_combination(tochar(in[1]) + in.substring(2,l-1));
add_combination(tochar(10*in[1]+in[2]) + in.substring(3,l-2));
}
In plain words take first 1 or 2 digit character and decode the rest of the string. Let assume your example 1125 the recursions will be as this:
||decode(1125)|
|1|decode(125)|
|1,1|decode(25)|
|1,1,2|decode(5)|
|1,1,2,5|decode()| - combination
|1,1,25|decode()| - combination
|1,12|decode(5)|
|1,12,5|decode()| - combination
|11|decode(25)|
|11,2|decode(5)|
|11,2,5|decode()| - combination
|11,25|decode()| - combination
The intendation represent recursion layer, the first part is current combination prefix (in0) and right part is the rest of string to decode (in1+i).
This sounds easy but to code this kind of feedback is bit more complicated. That is because wee need to remember a list of solutions instead of one. I decided to store all results in single string separated by \r\l end of lines. Here working VCL/C++ example:
//---------------------------------------------------------------------------
AnsiString txt_encode0(const AnsiString &in) // <'a','z'> -> <0,25>
{
int i,l=in.Length();
AnsiString txt="";
for (i=1;i<=l;i++) txt+=int(in[i]-'a');
return txt;
}
//---------------------------------------------------------------------------
AnsiString txt_encode1(const AnsiString &in) // <'a','z'> -> <1,26>
{
int i,l=in.Length();
AnsiString txt="";
for (i=1;i<=l;i++) txt+=int(in[i]-'a'+1);
return txt;
}
//---------------------------------------------------------------------------
void txt_decode0(AnsiString &out,AnsiString in0,const AnsiString &in1,int i,int &l) // recursion <0,25> -> <'a','z'>
{
// stop recursion if whole string processed
if (i>l) { out+=in0+"\r\n"; return; }
int a0,a1;
// load first 2 digits from i if second digit is not applicable set is as -1
a0=in1[i]-'0'; i++;
if (i<= l) a1=in1[i]-'0'; else a1=-1;
if (a0> 2) a1=-1; // >2 means always 1 digit code
if (a0==0) a1=-1; // =0 means always 1 digit code
// one digit combination
in0+=char(a0+'a');
txt_decode0(out,in0,in1,i,l);
in0.SetLength(in0.Length()-1);
// 2 digit combination
if (a1>=0)
{
a0*=10;
a0+=a1; i++;
if (a0<=26)
{
in0+=char(a0+'a');
txt_decode0(out,in0,in1,i,l);
}
}
}
AnsiString txt_decode0(const AnsiString &in) // <0,25> -> <'a','z'>
{
int l=in.Length();
AnsiString in0="",out="";
txt_decode0(out,in0,in,1,l);
return out;
}
//---------------------------------------------------------------------------
void txt_decode1(AnsiString &out,AnsiString in0,const AnsiString &in1,int i,int &l) // recursion <1,26> -> <'a','z'>
{
// stop recursion if whole string processed
if (i>l) { out+=in0+"\r\n"; return; }
int a0,a1;
// load first 2 digits from i if second digit is not applicable set is as -1
a0=in1[i]-'0'; i++;
if (i<=l) a1=in1[i]-'0'; else a1=-1;
if (a0> 2) a1=-1; // >2 means always 1 digit code
// one digit combination
if (a1!=0) // =0 means always 2 digit code
{
in0+=char(a0+'a'-1);
txt_decode1(out,in0,in1,i,l);
in0.SetLength(in0.Length()-1);
}
// 2 digit combination
if (a1>=0)
{
a0*=10;
a0+=a1; i++;
if (a0<=26)
{
in0+=char(a0+'a'-1);
txt_decode1(out,in0,in1,i,l);
}
}
}
AnsiString txt_decode1(const AnsiString &in) // <1,26> -> <'a','z'>
{
int l=in.Length();
AnsiString in0="",out="";
txt_decode1(out,in0,in,1,l);
return out;
}
//---------------------------------------------------------------------------
void main()
{
AnsiString enc,dec,txt;
txt="decoding";
enc=txt_encode0(txt);
// enc="302213";
dec=txt_decode0(enc);
}
//---------------------------------------------------------------------------
The txt_encode0,txt_decode0 operates on <0,25> and txt_encode1,txt_decode1 operates on <1,26> range.
The out is holding list of valid combinations. in0 holds actual prefix of combination in1 hold the input string. i is start index for actual combination in in1 and l is length of in1. Here the output for <0,25>:
message:decoding
encoded:3421438136
decoded in [ 0.013 ms]
decbedibdg
decbeding
decodibdg
decoding
devedibdg
deveding
and your sample:
encoded:302213
decoded in [ 0.007 ms]
daccbd
daccn
dacvd
dawbd
dawn
I am using AnsiString from VCL they are self allocating dynamic strings with indexing from 1. For example AnsiString s="abc"; s[1]=='a' The size of it is s.Length() so s[s.Length()]=='c'.
Here's a recursive approach in JavaScript. The idea is if the next two characters in the string can be interpreted in two ways, add each of the two ways to each result in splitting the next part of the string. Otherwise, add just the first character to each result in splitting the next part of the string.
function possibilities(str){
if (str.length === 0) return [[]];
var result = [], next = possibilities(str.substr(1));
for (var i=0; i<next.length; i++)
result.push([str[0]].concat(next[i]));
if (str.length > 1 && str[0] !== '0' && str.substr(0,2) < 27){
next = possibilities(str.substr(2));
for (var i=0; i<next.length; i++)
result.push([str.substr(0,2)].concat(next[i]));
}
return result;
}
console.log(possibilities('1125'));
console.log(possibilities('302213'));
Related
I’m using this character, double sharp '𝄪' which unicode is 0x1d12a.
If I use it in a string, I can’t get the correct string length:
str = "F𝄪"
str.length // returns 3, even though there are 2 characters!
How do I get the function to return the correct answer, whether or not I’m using special unicode or not ?
String.prototype.codes = function() { return [...this].length };
String.prototype.chars = function() {
let GraphemeSplitter = require('grapheme-splitter');
return (new GraphemeSplitter()).countGraphemes(this);
}
console.log("F𝄪".codes()); // 2
console.log("👩❤️💋👩".codes()); // 8
console.log("❤️".codes()); // 2
console.log("F𝄪".chars()); // 2
console.log("👩❤️💋👩".chars()); // 1
console.log("❤️".chars()); // 1
That's the function I wrote to get string length in codepoint length
function nbUnicodeLength(string){
var stringIndex = 0;
var unicodeIndex = 0;
var length = string.length;
var second;
var first;
while (stringIndex < length) {
first = string.charCodeAt(stringIndex); // returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.
if (first >= 0xD800 && first <= 0xDBFF && string.length > stringIndex + 1) {
second = string.charCodeAt(stringIndex + 1);
if (second >= 0xDC00 && second <= 0xDFFF) {
stringIndex += 2;
} else {
stringIndex += 1;
}
} else {
stringIndex += 1;
}
unicodeIndex += 1;
}
return unicodeIndex;
}
To sumarize my comments:
That's just the lenght of that string.
Some chars involve other chars as well, even if it looks like a single character. "̉mủt̉ả̉̉̉t̉ẻd̉W̉ỏ̉r̉̉d̉̉".length == 24
From this (great) blog post, they have a function that will return correct length:
function fancyCount(str){
const joiner = "\u{200D}";
const split = str.split(joiner);
let count = 0;
for(const s of split){
//removing the variation selectors
const num = Array.from(s.split(/[\ufe00-\ufe0f]/).join("")).length;
count += num;
}
//assuming the joiners are used appropriately
return count / split.length;
}
console.log(fancyCount("F𝄪") == 2) // true
Javascript (and Java) strings use UTF-16 encoding.
Unicode codepoint U+0046 (F) is encoded in UTF-16 using 1 codeunit: 0x0046
Unicode codepoint U+1D12A (𝄪) is encoded in UTF-16 using 2 codeunits (known as a "surrogate pair"): 0xD834 0xDD2A
That is why you are getting a length of 3, not 2. The length counts the number of encoded codeunits, not the number of Unicode codepoints.
I was given the challenge of converting a string of digits into 'fake binary' on Codewars.com, and I am to convert each individual digit into a 0 or a 1, if the number is less than 5 it should become a 0, and if it's 5 or over it should become a 1. I know how to analyze the whole string's value like so:
function fakeBin(x){
if (x < 5)
return 0;
else return 1;
}
This however, analyzes the value of the whole string, how would I go about analyzing each individual digit within the string rather than the whole thing?
Note: I have already looked at the solutions on the website and don't understand them, I'm not cheating.
You can do it in one line with two simple global string replacement operations:
function fakeBin(x){
return ("" + x).replace(/[0-4]/g,'0').replace(/[5-9]/g,'1');
}
console.log(fakeBin(1259))
console.log(fakeBin(7815))
console.log(fakeBin("1234567890"))
The ("" + x) part is just to ensure you have a string to work with, so the function can take numbers or strings as input (as in my example calls above).
Simple javascript solution to achieve expected solution
function fakeBin(x){
x = x+'' ;
var z =[];
for(var i=0;i< x.length;i++){
if((x[i]*1)<5){
z[i] =0;
}else{
z[i]=1;
}
}
return z
}
console.log(fakeBin(357))
The snippet below will take a string and return a new string comprised of zeros and/or ones based on what you described.
We use a for ...of loop to traverse the input string and will add a 0 or 1 to our return array based on whether the parsed int if greater or less than 5.
Also note that we are checking and throwing an error if the character is not a number.
const word = "1639";
const stringToBinary = function(str) {
let ret = [];
for (const char of word) {
if (Number.isNaN(parseInt(char, 10))) {
throw new Error(`${char} is not a digit!`);
} else {
const intVal = parseInt(char, 10);
ret.push(intVal > 5 ? 1 : 0);
}
}
return ret.join('');
};
console.log(stringToBinary(word));
if you are in java you can use
charAt()
and you make a for with the word length and you can check one by one
for(int i = 0; i < text.length(); i++){
yourfunction(texto.charAt(i));
}
Split the string and apply the current function you have to each element of the string. You can accomplish this with map or with reduce:
function fakeBin(x) {
x = x.split('');
let toBin = x => {
if (x < 5)
return 0;
else return 1
}
return x.map(toBin).join('');
}
console.log(fakeBin("2351"));
refactored
function fakeBin(x) {
x = [...x];
let toBin = x => x < 5 ? 0 : 1;
return x.map(toBin).join('');
}
console.log(fakeBin("2351"));
reduce
function fakeBin(x) {
let toBin = x => x < 5 ? 0 : 1;
return [...x].reduce((acc,val) => acc + toBin(val), "");
}
console.log(fakeBin("23519"));
You can use String.prototype.replace() with RegExp /([0-4])|([5-9])/g to match 0-4, 5-9, replace with 0, 1 respectively
let str = "8539734222673566";
let res = str.replace(/([0-4])|([5-9])/g, (_, p1, p2) => p1 ? 0 : 1);
console.log(res);
I've looked this up online without much results because it's quite hard to describe in a few words.
Basically, I need to have a function, say puntil which takes the argument string. Basically, the function permutes until the string is equal to the argument.
For example if you run puntil('ab') it should do inside the function:
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
aa
ab !! MATCH
Another example, for puntil('abcd') it will do
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
aa
ab
ac
ad
ae
af
ag
ah
ai
aj
ak
al
am
an
ao
ap
aq
ar
as
at
au
av
aw
ax
ay
az
... etc etc ..
until it matches abcd.
Basically an infinite permutation until it matches.
Any ideas?
Here is the fiddle
var alphabet = ['a','b','c'];//,'d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var output = "";
var match = "cccc"; //<----------- match here
//This is your main function
function permutate() {
var d = 0; // d for depth
while (true) {
//Your main alphabet iteration
for (var i=0; i<alphabet.length; i++){
//First level
if (d === 0) {
console.log(alphabet[i])
output = alphabet[i];
}
else
iterator(alphabet[i], d); //Call iterator for d > 0
if (output === match)
return;
}
d++; //Increase the depth
}
}
//This function runs n depths of iterations
function iterator(s, depth){
if (depth === 0)
return;
for (var i=0; i<alphabet.length; i++){
if (depth > 1)
iterator(s + alphabet[i], depth - 1)
else {
console.log(s + alphabet[i]);
output = s + alphabet[i];
}
if (output === match)
return;
}
};
Explanation:
Your program needs to traverse a tree of alphabet like this
[a]
-[a]
-[a]
-[a]...
-[b]...
[b] ...
-[b] -
-[a]...
-[b]...
[b] - ...
[c] - ...
This could have easily been done through a conventional recursive function if not for the requirement that you need to finish each depth first.
So we need a special iterator(s, depth) function which can perform number of nested iterations (depth) requested.
So the main function can call the iterator with increasing depths (d++).
That's all!!
Warning: This is a prototype only. This can be optimized and improved. It uses global variables for the ease of demonstrating. Your real program should avoid globals. Also I recommend calling the iterator() inside setTimeout if your match word is too long.
The n depths can only be limited by your resources.
Fiddle here
function next(charArray, rightBound){
if(!rightBound){
rightBound = charArray.length;
}
var oldValue = charArray[rightBound-1];
var newValue = nextCharacter(charArray[rightBound-1]);
charArray[rightBound-1] = newValue;
if(newValue < oldValue){
if(rightBound > 1){
next(charArray, rightBound-1);
}
else{
charArray.push('a');
}
}
return charArray;
}
function nextCharacter(char){
if(char === 'z'){
return 'a'
}
else{
return String.fromCharCode(char.charCodeAt(0) + 1)
}
}
function permuteUntil(word){
var charArray = ['a'];
var wordChain = ['a'];
while(next(charArray).join('') !== word){
wordChain.push(charArray.join(''));
}
wordChain.push(word);
return wordChain.join(', ');
}
alert(permuteUntil('ab'));
What OP is asking is a bit ambiguous, so I'll post for both the things (that I doubt) OP is asking.
First, the question can be, what will be the position of input string in the infinite permutation of alphabets (which I see as more legit question, I've given the reason later). This can be done in the following manner:
Taking an example (input = dhca). So, all strings of 1 to 3 characters length will come before this string. So, add: 26^1 + 26^2 + 26^3 to the answer. Then, 1st character is d, which means, following the dictionary, if 1st character is a | b | c, all characters past that are valid. So, add 3 * 26^3 to the answer. Now, say 1st character is d. Then, we can have all characters from a to g (7) and last 2 characters can be anything. So, add 7 * 26^2 to the answer. Going on in this way, we get the answer as:
26^1 + 26^2 + 26^3 + (3 * 26^3) + (7 * 26^2) + (2 * 26^1) + (0) + 1
= 75791
OK. Now the second thing, which I think OP is actually asking (to print all strings before we get a match). Now, why I think this is unfeasible is because if we have input as zzzzz (5 characters long) we need to print 26^1 + 26^2 + 26^3 + 26^4 + 26^5 strings, which is 12356630. So, for this part, I assume max length of input string is 5 (And definitely no more) because for 6 character length string, we need to print ~321272406 strings --> NOT POSSIBLE.
So, a simple solution to this can be:
Create an array of size 27 as: arr[] = {'', 'a', 'b', ..., 'y', 'z'}. 1st character is null.
Write 5 (max string length) nested loops from 0 to 26 (inclusive) and add it to dummy string and print it. Something like.
for i from 0 to 26
String a = "" + arr[i]
for j from 0 to 26
String b = a + arr[j]
for k from 0 to 26
String c = b + arr[k]
for l from 0 to 26
String d = c + arr[l]
for m from 0 to 26
String e = d + arr[m]
print e
if(e equals input string)
break from all loops //use some flag, goto statement etc.
You asked for a more elegant solution, here's a simple function that converts integers into lowercase strings of characters allowing you to easily iterate through strings.
function toWord(val, first, out) {
if(first == 1)
out = String.fromCharCode(97 + val % 26) + out;
else
out = String.fromCharCode(97 + (val-1) % 26) + out;
if(val % 26 == 0 && first == 0) {
val -= 26;
}
else {
val -= val %26;
}
val = val / 26;
if(val != 0)
return toWord(val, 0, out);
else
return out;
}
It's by no means perfect, but it's short and simple. When calling the function set val to be the integer you want to convert, first as 1, and out as "".
For example the following will apply yourFunction to the first 10,000 lowercase strings
for(int i=0; i<10000; i++) {
youFunction(toWord(i, 1, ""));
}
So you need to always start incrementing from a? Since they are char values you can easily do this with the following construct:
Note that this is a java solution :)
public static char[] increment(char[] arr, int pos) {
// get current position char
char currentChar = arr[pos];
// increment it by one
currentChar++;
// if it is at the end of it's range
boolean overflow = false;
if (currentChar > 'Z') {
overflow = true;
currentChar = 'A';
}
// always update current char
arr[pos] = currentChar;
if (overflow) {
if (pos == 0) {
// resize array and add new character
char[] newArr = new char[arr.length + 1];
System.arraycopy(arr, 0, newArr, 0, arr.length);
newArr[arr.length] = 'A';
arr = newArr;
} else {
// overflowed, increment one position back
arr = increment(arr, pos - 1);
}
}
return arr;
}
public static void main(String[] args) {
final String stringToUse = "A";
final String stringToSearch = "ABCD";
char[] use = stringToUse.toCharArray();
for (;;) {
final String result = new String(use);
System.out.println("Candidate: " + result);
if (stringToSearch.equals(result)) {
System.out.println("Found!");
break;
}
use = increment(use, use.length - 1);
}
}
I wonder how to write palindrome in javascript, where I input different words and program shows if word is palindrome or not. For example word noon is palindrome, while bad is not.
Thank you in advance.
function palindrome(str) {
var len = str.length;
var mid = Math.floor(len/2);
for ( var i = 0; i < mid; i++ ) {
if (str[i] !== str[len - 1 - i]) {
return false;
}
}
return true;
}
palindrome will return if specified word is palindrome, based on boolean value (true/false)
UPDATE:
I opened bounty on this question due to performance and I've done research and here are the results:
If we are dealing with very large amount of data like
var abc = "asdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfdasdhfkahkjdfhkaksjdfhaksdfjhakjddfhkjahksdhfaiuyqewiuryiquweyriyqiuweyriuqiuweryiquweyriuqyweirukajsdhfkahdfjkhakjsdhfkahksdhfakhdjkfqwiueryqiueyriuasdkfjhakjhdfkjashfkajhsdfkjahsdkalsdjflkasjdfljqoiweurasldjflasfd";
for ( var i = 0; i < 10; i++ ) {
abc += abc; // making string even more larger
}
function reverse(s) { // using this method for second half of string to be embedded
return s.split("").reverse().join("");
}
abc += reverse(abc); // adding second half string to make string true palindrome
In this example palindrome is True, just to note
Posted palindrome function gives us time from 180 to 210 Milliseconds (in current example), and the function posted below
with string == string.split('').reverse().join('') method gives us 980 to 1010 Milliseconds.
Machine Details:
System: Ubuntu 13.10
OS Type: 32 Bit
RAM: 2 Gb
CPU: 3.4 Ghz*2
Browser: Firefox 27.0.1
Try this:
var isPalindrome = function (string) {
if (string == string.split('').reverse().join('')) {
alert(string + ' is palindrome.');
}
else {
alert(string + ' is not palindrome.');
}
}
document.getElementById('form_id').onsubmit = function() {
isPalindrome(document.getElementById('your_input').value);
}
So this script alerts the result, is it palindrome or not. You need to change the your_id with your input id and form_id with your form id to get this work.
Demo!
Use something like this
function isPalindrome(s) {
return s === s.split("").reverse().join("") ? true : false;
}
alert(isPalindrome("noon"));
alternatively the above code can be optimized as [updated after rightfold's comment]
function isPalindrome(s) {
return s === s.split("").reverse().join("");
}
alert(isPalindrome("malayalam"));
alert(isPalindrome("english"));
Faster Way:
-Compute half the way in loop.
-Store length of the word in a variable instead of calculating every time.
EDIT:
Store word length/2 in a temporary variable as not to calculate every time in the loop as pointed out by (mvw) .
function isPalindrome(word){
var i,wLength = word.length-1,wLengthToCompare = wLength/2;
for (i = 0; i <= wLengthToCompare ; i++) {
if (word.charAt(i) != word.charAt(wLength-i)) {
return false;
}
}
return true;
}
Let us start from the recursive definition of a palindrome:
The empty string '' is a palindrome
The string consisting of the character c, thus 'c', is a palindrome
If the string s is a palindrome, then the string 'c' + s + 'c' for some character c is a palindrome
This definition can be coded straight into JavaScript:
function isPalindrome(s) {
var len = s.length;
// definition clauses 1. and 2.
if (len < 2) {
return true;
}
// note: len >= 2
// definition clause 3.
if (s[0] != s[len - 1]) {
return false;
}
// note: string is of form s = 'a' + t + 'a'
// note: s.length >= 2 implies t.length >= 0
var t = s.substr(1, len - 2);
return isPalindrome(t);
}
Here is some additional test code for MongoDB's mongo JavaScript shell, in a web browser with debugger replace print() with console.log()
function test(s) {
print('isPalindrome(' + s + '): ' + isPalindrome(s));
}
test('');
test('a');
test('ab');
test('aa');
test('aab');
test('aba');
test('aaa');
test('abaa');
test('neilarmstronggnortsmralien');
test('neilarmstrongxgnortsmralien');
test('neilarmstrongxsortsmralien');
I got this output:
$ mongo palindrome.js
MongoDB shell version: 2.4.8
connecting to: test
isPalindrome(): true
isPalindrome(a): true
isPalindrome(ab): false
isPalindrome(aa): true
isPalindrome(aab): false
isPalindrome(aba): true
isPalindrome(aaa): true
isPalindrome(abaa): false
isPalindrome(neilarmstronggnortsmralien): true
isPalindrome(neilarmstrongxgnortsmralien): true
isPalindrome(neilarmstrongxsortsmralien): false
An iterative solution is:
function isPalindrome(s) {
var len = s.length;
if (len < 2) {
return true;
}
var i = 0;
var j = len - 1;
while (i < j) {
if (s[i] != s[j]) {
return false;
}
i += 1;
j -= 1;
}
return true;
}
Look at this:
function isPalindrome(word){
if(word==null || word.length==0){
// up to you if you want true or false here, don't comment saying you
// would put true, I put this check here because of
// the following i < Math.ceil(word.length/2) && i< word.length
return false;
}
var lastIndex=Math.ceil(word.length/2);
for (var i = 0; i < lastIndex && i< word.length; i++) {
if (word[i] != word[word.length-1-i]) {
return false;
}
}
return true;
}
Edit: now half operation of comparison are performed since I iterate only up to half word to compare it with the last part of the word. Faster for large data!!!
Since the string is an array of char no need to use charAt functions!!!
Reference: http://wiki.answers.com/Q/Javascript_code_for_palindrome
Taking a stab at this. Kind of hard to measure performance, though.
function palin(word) {
var i = 0,
len = word.length - 1,
max = word.length / 2 | 0;
while (i < max) {
if (word.charCodeAt(i) !== word.charCodeAt(len - i)) {
return false;
}
i += 1;
}
return true;
}
My thinking is to use charCodeAt() instead charAt() with the hope that allocating a Number instead of a String will have better perf because Strings are variable length and might be more complex to allocate. Also, only iterating halfway through (as noted by sai) because that's all that's required. Also, if the length is odd (ex: 'aba'), the middle character is always ok.
Best Way to check string is palindrome with more criteria like case and special characters...
function checkPalindrom(str) {
var str = str.replace(/[^a-zA-Z0-9]+/gi, '').toLowerCase();
return str == str.split('').reverse().join('');
}
You can test it with following words and strings and gives you more specific result.
1. bob
2. Doc, note, I dissent. A fast never prevents a fatness. I diet on cod
For strings it ignores special characters and convert string to lower case.
String.prototype.isPalindrome = function isPalindrome() {
const cleanString = this.toLowerCase().replace(/\s+/g, '');
const cleanStringRevers = cleanString.split("").reverse().join("");
return cleanString === cleanStringRevers;
}
let nonPalindrome = 'not a palindrome';
let palindrome = 'sugus';
console.log(nonPalindrome.isPalindrome())
console.log(palindrome.isPalindrome())
The most important thing to do when solving a Technical Test is Don't use shortcut methods -- they want to see how you think algorithmically! Not your use of methods.
Here is one that I came up with (45 minutes after I blew the test). There are a couple optimizations to make though. When writing any algorithm, its best to assume false and alter the logic if its looking to be true.
isPalindrome():
Basically, to make this run in O(N) (linear) complexity you want to have 2 iterators whose vectors point towards each other. Meaning, one iterator that starts at the beginning and one that starts at the end, each traveling inward. You could have the iterators traverse the whole array and use a condition to break/return once they meet in the middle, but it may save some work to only give each iterator a half-length by default.
for loops seem to force the use of more checks, so I used while loops - which I'm less comfortable with.
Here's the code:
/**
* TODO: If func counts out, let it return 0
* * Assume !isPalindrome (invert logic)
*/
function isPalindrome(S){
var s = S
, len = s.length
, mid = len/2;
, i = 0, j = len-1;
while(i<mid){
var l = s.charAt(i);
while(j>=mid){
var r = s.charAt(j);
if(l === r){
console.log('#while *', i, l, '...', j, r);
--j;
break;
}
console.log('#while !', i, l, '...', j, r);
return 0;
}
++i;
}
return 1;
}
var nooe = solution('neveroddoreven'); // even char length
var kayak = solution('kayak'); // odd char length
var kayaks = solution('kayaks');
console.log('#isPalindrome', nooe, kayak, kayaks);
Notice that if the loops count out, it returns true. All the logic should be inverted so that it by default returns false. I also used one short cut method String.prototype.charAt(n), but I felt OK with this as every language natively supports this method.
This function will remove all non-alphanumeric characters (punctuation, spaces, and symbols) and turn everything lower case in order to check for palindromes.
function palindrome(str){
var re = /[^A-Za-z0-9]/g;
str = str.toLowerCase().replace(re, '');
return str == str.split('').reverse().join('') ? true : false;
}
Here is an optimal and robust solution for checking string palindrome using ES6 features.
const str="madam"
var result=[...str].reduceRight((c,v)=>((c+v)))==str?"Palindrome":"Not Palindrome";
console.log(result);
Try this
isPalindrome = (string) => {
if (string === string.split('').reverse().join('')) {
console.log('is palindrome');
}
else {
console.log('is not palindrome');
}
}
isPalindrome(string)
Here's a one-liner without using String.reverse,
const isPal = str => [...new Array(strLen = str.length)]
.reduce((acc, s, i) => acc + str[strLen - (i + 1)], '') === str;
function palindrome(str) {
var lenMinusOne = str.length - 1;
var halfLen = Math.floor(str.length / 2);
for (var i = 0; i < halfLen; ++i) {
if (str[i] != str[lenMinusOne - i]) {
return false;
}
}
return true;
}
Optimized for half string parsing and for constant value variables.
I think following function with time complexity of o(log n) will be better.
function palindrom(s){
s = s.toString();
var f = true; l = s.length/2, len = s.length -1;
for(var i=0; i < l; i++){
if(s[i] != s[len - i]){
f = false;
break;
}
}
return f;
}
console.log(palindrom(12321));
Here's another way of doing it:
function isPalin(str) {
str = str.replace(/\W/g,'').toLowerCase();
return(str==str.split('').reverse().join(''));
}
Below code tells how to get a string from textBox and tell you whether it is a palindrome are not & displays your answer in another textbox
<html>
<head>
<meta charset="UTF-8"/>
<link rel="stylesheet" href=""/>
</head>
<body>
<h1>1234</h1>
<div id="demo">Example</div>
<a accessKey="x" href="http://www.google.com" id="com" >GooGle</a>
<h1 id="tar">"This is a Example Text..."</h1>
Number1 : <input type="text" name="txtname" id="numb"/>
Number2 : <input type="text" name="txtname2" id="numb2"/>
Number2 : <input type="text" name="txtname3" id="numb3" />
<button type="submit" id="sum" onclick="myfun()" >count</button>
<button type="button" id="so2" onclick="div()" >counnt</button><br/><br/>
<ol>
<li>water</li>
<li>Mazaa</li>
</ol><br/><br/>
<button onclick="myfun()">TryMe</button>
<script>
function myfun(){
var pass = document.getElementById("numb").value;
var rev = pass.split("").reverse().join("");
var text = document.getElementById("numb3");
text.value = rev;
if(pass === rev){
alert(pass + " is a Palindrome");
}else{
alert(pass + " is Not a Palindrome")
}
}
</script>
</body>
</html>
25x faster + recursive + non-branching + terse
function isPalindrome(s,i) {
return (i=i||0)<0||i>=s.length>>1||s[i]==s[s.length-1-i]&&isPalindrome(s,++i);
}
See my complete explanation here.
The code is concise quick fast and understandable.
TL;DR
Explanation :
Here isPalindrome function accepts a str parameter which is typeof string.
If the length of the str param is less than or equal to one it simply returns "false".
If the above case is false then it moves on to the second if statement and checks that if the character at 0 position of the string is same as character at the last place. It does an inequality test between the both.
str.charAt(0) // gives us the value of character in string at position 0
str.slice(-1) // gives us the value of last character in the string.
If the inequality result is true then it goes ahead and returns false.
If result from the previous statement is false then it recursively calls the isPalindrome(str) function over and over again until the final result.
function isPalindrome(str){
if (str.length <= 1) return true;
if (str.charAt(0) != str.slice(-1)) return false;
return isPalindrome(str.substring(1,str.length-1));
};
document.getElementById('submit').addEventListener('click',function(){
var str = prompt('whats the string?');
alert(isPalindrome(str))
});
document.getElementById('ispdrm').onsubmit = function(){alert(isPalindrome(document.getElementById('inputTxt').value));
}
<!DOCTYPE html>
<html>
<body>
<form id='ispdrm'><input type="text" id="inputTxt"></form>
<button id="submit">Click me</button>
</body>
</html>
function palindrome(str) {
var re = /[^A-Za-z0-9]/g;
str = str.toLowerCase().replace(re, '');
var len = str.length;
for (var i = 0; i < len/2; i++) {
if (str[i] !== str[len - 1 - i]) {
return false;
}
}
return true;
}
Or you could do it like this.
var palindrome = word => word == word.split('').reverse().join('')
How about this one?
function pall (word) {
var lowerCWord = word.toLowerCase();
var rev = lowerCWord.split('').reverse().join('');
return rev.startsWith(lowerCWord);
}
pall('Madam');
str1 is the original string with deleted non-alphanumeric characters and spaces and str2 is the original string reversed.
function palindrome(str) {
var str1 = str.toLowerCase().replace(/\s/g, '').replace(
/[^a-zA-Z 0-9]/gi, "");
var str2 = str.toLowerCase().replace(/\s/g, '').replace(
/[^a-zA-Z 0-9]/gi, "").split("").reverse().join("");
if (str1 === str2) {
return true;
}
return false;
}
palindrome("almostomla");
function isPalindrome(s) {
return s == reverseString(s);
}
console.log((isPalindrome("abcba")));
function reverseString(str){
let finalStr=""
for(let i=str.length-1;i>=0;i--){
finalStr += str[i]
}
return finalStr
}
Frist I valid this word with converting lowercase and removing whitespace and then compare with reverse word within parameter word.
function isPalindrome(input) {
const toValid = input.trim("").toLowerCase();
const reverseWord = toValid.split("").reverse().join("");
return reverseWord == input.toLowerCase().trim() ? true : false;
}
isPalindrome(" madam ");
//true
This answer is easy to read and I tried to explain by using comment. Check the code below for How to write Palindrome in JavaScript.
Step 1: Remove all non-alphanumeric characters (punctuation, spaces and symbols) from Argument string 'str' using replace() and then convert in to lowercase using toLowerCase().
Step 2: Now make string reverse. first split the string into the array using split() then reverse the array using reverse() then make the string by joining array elements using join() .
Step 3: Find the first character of nonAlphaNumeric string using charAt(0).
Step 4: Find the Last character of nonAlphaNumeric string using charAt(length of nonAlphaNumeric string - 1).
Step 5: Use If condition to chack nonAlphaNumeric string and reverse string is same or not.
Step 6: Use another If condition to chack first character of nonAlphaNumeric string is same to Last character of nonAlphaNumeric string.
function palindrome(str) {
var nonAlphaNumericStr = str.replace(/[^0-9A-Za-z]/g, "").toLowerCase(); // output - e1y1e
var reverseStr = nonAlphaNumericStr.split("").reverse().join(""); // output - e1y1e
var firstChar = nonAlphaNumericStr.charAt(0); // output - e
var lastChar = nonAlphaNumericStr.charAt(nonAlphaNumericStr.length - 1); // output - e
if(nonAlphaNumericStr === reverseStr) {
if(firstChar === lastChar) {
return `String is Palindrome`;
}
}
return `String is not Palindrome`;
}
console.log(palindrome("_eye"));
function check(txt)
{
for (var i = txt.length; i >= 0; i--)
if (txt[i] !== txt[txt.length - 1 - i])
return console.log('not palidrome');
return console.log(' palidrome');
}
check('madam');
Note: This is case sensitive
function palindrome(word)
{
for(var i=0;i<word.length/2;i++)
if(word.charAt(i)!=word.charAt(word.length-(i+1)))
return word+" is Not a Palindrome";
return word+" is Palindrome";
}
Here is the fiddle: http://jsfiddle.net/eJx4v/
I am not sure how this JSPerf check the code performance. I just tried to reverse the string & check the values. Please comment about the Pros & Cons of this method.
function palindrome(str) {
var re = str.split(''),
reArr = re.slice(0).reverse();
for (a = 0; a < re.length; a++) {
if (re[a] == reArr[a]) {
return false;
} else {
return true;
}
}
}
JS Perf test
Example: We have the number 1122. I would like to check that if given number contains the digit 1 more than once. In this case, it should return true.
I need the code to be flexible, it has to work with any number, like 3340, 5660, 4177 etc.
You can easily "force" JS to coerce any numeric value to a string, either by calling the toString method, or concatenating:
var someNum = 1122;
var oneCount = (someNum + '').split('1').length;
by concatenating a number to an empty string, the variable is coerced to a string, so you can use all the string methods you like (.match, .substring, .indexOf, ...).
In this example, I've chosen to split the string on each '1' char, count and use the length of the resulting array. If the the length > 2, than you know what you need to know.
var multipleOnes = ((someNum + '').split('1').length > 2);//returns a bool, true in this case
In response to your comment, to make it flexible - writing a simple function will do:
function multipleDigit(number, digit, moreThan)
{
moreThan = (moreThan || 1) + 1;//default more than 1 time, +1 for the length at the end
digit = (digit !== undefined ? digit : 1).toString();
return ((someNum + '').split(digit).length > moreThan);
}
multipleDigit(1123, 1);//returns true
multipleDigit(1123, 1, 2);//returns false
multipleDigit(223344,3);//returns 3 -> more than 1 3 in number.
Use javascript's match() method. Essentially, what you'd need to do is first convert the number to a string. Numbers don't have the RegExp methods. After that, match for the number 1 globally and count the results (match returns an array with all matched results).
var number = 1100;
console.log(number.toString().match(/1/g).length);
function find(num, tofind) {
var b = parseInt(num, 10);
var c = parseInt(tofind, 10);
var a = c.split("");
var times = 0;
for (var i = 0; i < a.length; i++) {
if (a[i] == b) {
times++;
}
}
alert(times);
}
find('2', '1122');
Convert the number to a string and iterate over it. Return true once a second digit has been found, for efficiency.
function checkDigitRepeat(number, digit) {
var i, count = 0;
i = Math.abs(number);
if(isNaN(i)) {
throw(TypeError('expected Number for number, got: ' + number));
}
number = i.toString();
i = Math.abs(digit);
if(isNaN(i)) {
throw(TypeError('expected Number for digit, got: ' + digit));
}
digit = i.toString();
if(digit > 9) {
throw(SyntaxError('expected a digit for digit, got a sequence of digits: ' + digit));
}
for(i = 0; i < number.length; i += 1) {
if(number[i] === digit) {
count += 1;
if(count >= 2) { return true; }
}
}
return false;
}
In the event that you want to check for a sequence of digits, your solution may lie in using regular expressions.
var myNum = '0011';
var isMultipleTimes = function(num) {
return !!num.toString().match(/(\d)\1/g);
}
console.log(isMultipleTimes(myNum));
JavaScript Match
Using #Aspiring Aqib's answer, I made a function that actually works properly and in the way I want.
The way it works is:
Example execution: multDig('221','2')
Split the number (first argument) to an array where each element is one digit.Output: ['2','2','1']
Run a for loop, which checks each of the array elements if they match with the digit (second argument), and increment the times variable if there is a match.Output: 2
Check inside the for loop if the match was detected already to improve performance on longer numbers like 2211111111111111
Return true if the number was found more than once, otherwise, return false.
And finally the code itself:
function multDig(number, digit){
var finalSplit = number.toString().split(''), times = 0;
for (i = 0; i < finalSplit.length; i++){
if (finalSplit[i] == digit){
times++
}
if (times > 1){
return true;
}
}
return false;
}