Run IndexOf more than one time JS - javascript

How to search multiple same values and look if it meets the conditions without regex? Suppose that I have this string ***6**5****8*9***2
What I need to do is to check if the string has at least three times *** altogether and then if the number before and after the *** sums 11. In the example given, these conditions are met because: First, the string has three *** altogether, and then 9 + 2 is 11.
I have solved this problem using regex, match, and replace, but how I can do it without applying to those solutions.
I have tried to do this without regex but it did not work because indexOf is only giving me one result:
string = "***6**5****8*9***2";
for (var i = 0; i < string.length; i++) {
let where = (string.indexOf("***"));
let a = parseInt(string.charAt(where - 1));
let b = parseInt(string.charAt(where + 3));
if (a + b == 11){
isTrue = true;
}
}

You could split the string by stars amd keep the starts in the array then check if the value starts with a star, check the length and the left and right element for sum.
var string = "***6**5****8*9***2",
parts = string.split(/(\*+)/),
result = parts.some((s, i, { [i - 1]: l, [i + 1]: r }) =>
s[0] === '*' && s.length >= 3 && +l + +r === 11
);
console.log(result);
console.log(parts);

I tried to create a solution based off of your existing code:
string = "***6**5****8*9***2***4";
let where = 0;
// Skip leading *
while (where < string.length && '*' == string.charAt(where)) {
where += 1;
}
while (true) {
// Find three stars based on previous result
where = string.indexOf("***", where);
// No more triples
if (where == -1) break;
// Convert to digit - will be NaN if not a digit
let a = parseInt(string.charAt(where - 1));
// Find trailing digit
let j = where + 1;
// Skip to next non * char
while (j < string.length && '*' == string.charAt(j)) {
j += 1;
}
// No matches - quit
if (j == string.length) break;
// Parse digit
let b = parseInt(string.charAt(j));
// Do the math
if (!isNaN(a) && !isNaN(b)){
console.log(`${a} + ${b} = ${a+b}`);
}
where = j;
}

I wrote a simple Parser.I hope it can help you
string = "***6**5****8*9***2";
class Parser {
static parse(string) {
var lexer = new Lexer(string);
var token = lexer.getToken();
var prevNumberToken = null ;
while (token.type !== TOKEN_TYPE_END) {
if(token.type === TOKEN_TYPE_NUMBER){
if(prevNumberToken && prevNumberToken.value + token.value === 11 ) {
return true;
}
prevNumberToken = token ;
} else if(token.type !== TOKEN_TYPE_THREESTARS){
prevNumberToken = null ;
}
token = lexer.getToken();
}
return false;
}
}
class Lexer {
constructor(string) {
this._string = string;
this._index = -1;
this._len = string.length;
}
getToken() {
if (this._index < 0) {
this._index = 0;
return new Token(TOKEN_TYPE_START, '', -1);
}
if (this._index >= this._len) {
return new Token(TOKEN_TYPE_END, '', this._len);
}
if (this._string[this._index] === "*") {
return this._getStarToken()
} else {
return this._getNumberToken();
}
}
_getStarToken() {
var stars = "";
var i = this._index;
while (this._index < this._len && this._string[this._index] === "*") {
stars += "*";
this._index++;
}
if (stars.length === 3) {
return new Token(TOKEN_TYPE_THREESTARS, stars, i)
}
return new Token(TOKEN_TYPE_STARS, stars, i)
}
_getNumberToken() {
var numbers = "";
var i = this._index;
while (this._index < this._len && this._string[this._index] !== "*") {
if (this._string[this._index] >= "0" && this._string[this._index] <= "90") {
numbers += this._string[this._index];
this._index++;
} else {
throw new Error("invalid character")
}
}
return new Token(TOKEN_TYPE_NUMBER, parseInt(numbers), i);
}
}
class Token {
constructor(type, value, index) {
this._type = type
this._index = index
this._value = value
}
get type() { return this._type }
get index() { return this._index }
get value() { return this._value }
}
const TOKEN_TYPE_START = 1;
const TOKEN_TYPE_NUMBER = 2;
const TOKEN_TYPE_THREESTARS = 4;
const TOKEN_TYPE_STARS = 8;
const TOKEN_TYPE_END = 16;
console.log(Parser.parse(string));

Related

Check if the string is a Palindrome using arrow Functiuons

I want to find if the user entered string is a Palindrome or not using arrow functions. But the code I have written is not showing an output....I dont understand whats wrong pls help....
var name = prompt("Enter Name: ");
const isPalindrome = name => {
const midPoint = name.length / 2;
for (let i = 0; i < midPoint && i < name.length; i++) {
if (name[i] != name[name.length - 1 - i]) {
console.log(" Not Palindrome");
}
}
console.log("Palindrome");
}
You can check for palindrome without a for loop.
function isPalindrome(string) {
const toArray = string.replace(/ /g, '').toLowerCase().split('');
const reverseArray = toArray.slice().reverse();
const original = toArray.join('');
const reversed = reverseArray.join('');
if (original === reversed) {
return true;
} else {
return false;
};
}
isPalindrome('WORD HERE');
use
isPalindrome(name)
under the code
All you have to do is just to call the function with the user input.
Also remember to return from the function once the input is not found as a palindrome. Else function will log both Not Palindrome and Palindrome when the input is not palindrome
var name = prompt("Enter Name: ");
const isPalindrome = name => {
const midPoint = name.length / 2;
for (let i = 0; i < midPoint && i < name.length; i++) {
if (name[i] != name[name.length - 1 - i]) {
console.log(" Not Palindrome");
return;
}
}
console.log("Palindrome");
}
isPalindrome(name);

The Odin Project - Fundamentals 4 Exercises - sumAll

I am stuck in the sumAll exercise from the Fundamentals 4 portion of the Odin Project. I managed to pass the test in which I need the result to be ‘ERROR’. However, I cannot figure out the correct code to pass the other tests. Where did I go wrong?
This is the exercise:
const sumAll = require(’./sumAll’)
describe(‘sumAll’, function() {
it(‘sums numbers within the range’, function() {
expect(sumAll(1, 4)).toEqual(10);
});
it(‘works with large numbers’, function() {
expect(sumAll(1, 4000)).toEqual(8002000);
});
it(‘works with larger number first’, function() {
expect(sumAll(123, 1)).toEqual(7626);
});
it(‘returns ERROR with negative numbers’, function() {
expect(sumAll(-10, 4)).toEqual(‘ERROR’);
});
it(‘returns ERROR with non-number parameters’, function() {
expect(sumAll(10, “90”)).toEqual(‘ERROR’);
});
it(‘returns ERROR with non-number parameters’, function() {
expect(sumAll(10, [90, 1])).toEqual(‘ERROR’);
});
});
My code:
const sumAll = function(a, b) {
const arr = [];
if (a < b) {
while (a <= b) {
arr.push(a++);
}
} else if (b < a) {
while (b <= a) {
arr.push(b++);
}
} else {
arr.push(a);
}
if (a < 0 || b < 0) {
return “ERROR”;
} else if (typeof a !== NaN || typeof b !== NaN) {
return “ERROR”;
}
return arr.reduce((a, b) => a + b);
}
module.exports = sumAll
I made in this way:
const sumAll = function (x, y) {
if (x > 0 && y > 0 && typeof x === 'number' && typeof y === 'number') {
var valorx = x;
var valory = y;
var total = 0;
if (x < y) {
for (var i = valorx; i <= valory; i++) {
total += i;
}
return total;
} else if (x > y) {
for (var i = valory; i <= valorx; i++) {
total += i;
}
return total;
}
} else {
return 'ERROR'
}
}
module.exports = sumAll
this how it work for me
const sumAll = function (startN, endN) {
//create variable to store total sum
let sum = 0;
check if input parameter in number:
if (typeof startN != "number" || typeof endN != "number") return "ERROR";
check if input numbers greter than 0:
else if (startN < 0 || endN < 0) return "ERROR";
and last check is, if last number greater than the first number then initial number will be the last number otherwise start number will be the initial:
else if (startN < endN) {
for (i = startN; i <= endN; i++) {
sum += i;
}
} else {
for (i = endN; i <= startN; i++) {
sum += i;
}
}
then return sum:
return sum;
};
you can make all these in one check but this are more readable.
That's how i did it. Quite similar but i avoided using for loops.
const sumAll = function(n,m) {
if (n<0 || m<0 || typeof(m) !== 'number' || typeof(n) !== 'number'){
return 'ERROR'
}else {
if(n<m){
n1 = n
n2 = m
}else{
n1 = m
n2 = n
}
return (n1+n2)*(n2/2)}
};
I first checked whether the input is valid, then decided the values of the two variables depending on which is bigger and finally calculated the sum.

Javascript anagram algorithm [duplicate]

I'm trying to compare two strings to see if they are anagrams.
My problem is that I'm only comparing the first letter in each string. For example, "Mary" and "Army" will return true but unfortunately so will "Mary" and Arms."
How can I compare each letter of both strings before returning true/false?
Here's a jsbin demo (click the "Console" tab to see the results"):
http://jsbin.com/hasofodi/1/edit
function compare (a, b) {
y = a.split("").sort();
z = b.split("").sort();
for (i=0; i<y.length; i++) {
if(y.length===z.length) {
if (y[i]===z[i]){
console.log(a + " and " + b + " are anagrams!");
break;
}
else {
console.log(a + " and " + b + " are not anagrams.");
break;
}
}
else {
console.log(a + " has a different amount of letters than " + b);
}
break;
}
}
compare("mary", "arms");
Instead of comparing letter by letter, after sorting you can join the arrays to strings again, and let the browser do the comparison:
function compare (a, b) {
var y = a.split("").sort().join(""),
z = b.split("").sort().join("");
console.log(z === y
? a + " and " + b + " are anagrams!"
: a + " and " + b + " are not anagrams."
);
}
If you want to write a function, without using inbuilt one, Check the below solution.
function isAnagram(str1, str2) {
if(str1 === str2) {
return true;
}
let srt1Length = str1.length;
let srt2Length = str2.length;
if(srt1Length !== srt2Length) {
return false;
}
var counts = {};
for(let i = 0; i < srt1Length; i++) {
let index = str1.charCodeAt(i)-97;
counts[index] = (counts[index] || 0) + 1;
}
for(let j = 0; j < srt2Length; j++) {
let index = str2.charCodeAt(j)-97;
if (!counts[index]) {
return false;
}
counts[index]--;
}
return true;
}
This considers case sensitivity and removes white spaces AND ignore all non-alphanumeric characters
function compare(a,b) {
var c = a.replace(/\W+/g, '').toLowerCase().split("").sort().join("");
var d = b.replace(/\W+/g, '').toLowerCase().split("").sort().join("");
return (c ===d) ? "Anagram":"Not anagram";
}
Quick one-liner solution with javascript functions - toLowerCase(), split(), sort() and join():
Convert input string to lowercase
Make array of the string with split()
Sort the array alphabetically
Now join the sorted array into a string using join()
Do the above steps to both strings and if after sorting strings are the same then it will be anargam.
// Return true if two strings are anagram else return false
function Compare(str1, str2){
if (str1.length !== str2.length) {
return false
}
return str1.toLowerCase().split("").sort().join("") === str2.toLowerCase().split("").sort().join("")
}
console.log(Compare("Listen", "Silent")) //true
console.log(Compare("Mary", "arms")) //false
No need for sorting, splitting, or joining. The following two options are efficient ways to go:
//using char array for fast lookups
const Anagrams1 = (str1 = '', str2 = '') => {
if (str1.length !== str2.length) {
return false;
}
if (str1 === str2) {
return true;
}
const charCount = [];
let startIndex = str1.charCodeAt(0);
for (let i = 0; i < str1.length; i++) {
const charInt1 = str1.charCodeAt(i);
const charInt2 = str2.charCodeAt(i);
startIndex = Math.min(charInt1, charInt2);
charCount[charInt1] = (charCount[charInt1] || 0) + 1;
charCount[charInt2] = (charCount[charInt2] || 0) - 1;
}
while (charCount.length >= startIndex) {
if (charCount.pop()) {
return false;
}
}
return true;
}
console.log(Anagrams1('afc','acf'))//true
console.log(Anagrams1('baaa','bbaa'))//false
console.log(Anagrams1('banana','bananas'))//false
console.log(Anagrams1('',' '))//false
console.log(Anagrams1(9,'hey'))//false
//using {} for fast lookups
function Anagrams(str1 = '', str2 = '') {
if (str1.length !== str2.length) {
return false;
}
if (str1 === str2) {
return true;
}
const lookup = {};
for (let i = 0; i < str1.length; i++) {
const char1 = str1[i];
const char2 = str2[i];
const remainingChars = str1.length - (i + 1);
lookup[char1] = (lookup[char1] || 0) + 1;
lookup[char2] = (lookup[char2] || 0) - 1;
if (lookup[char1] > remainingChars || lookup[char2] > remainingChars) {
return false;
}
}
for (let i = 0; i < str1.length; i++) {
if (lookup[str1[i]] !== 0 || lookup[str2[i]] !== 0) {
return false;
}
}
return true;
}
console.log(Anagrams('abc', 'cba'));//true
console.log(Anagrams('abcc', 'cbaa')); //false
console.log(Anagrams('abc', 'cde')); //false
console.log(Anagrams('aaaaaaaabbbbbb','bbbbbbbbbaaaaa'));//false
console.log(Anagrams('banana', 'ananab'));//true
Cleanest and most efficient solution for me
function compare(word1, word2) {
const { length } = word1
if (length !== word2.length) {
return false
}
const charCounts = {}
for (let i = 0; i < length; i++) {
const char1 = word1[i]
const char2 = word2[i]
charCounts[char1] = (charCounts[char1] || 0) + 1
charCounts[char2] = (charCounts[char2] || 0) - 1
}
for (const char in charCounts) {
if (charCounts[char]) {
return false
}
}
return true
}
I modified your function to work.
It will loop through each letter of both words UNTIL a letter doesn't match (then it knows that they AREN'T anagrams).
It will only work for words that have the same number of letters and that are perfect anagrams.
function compare (a, b) {
y = a.split("").sort();
z = b.split("").sort();
areAnagrams = true;
for (i=0; i<y.length && areAnagrams; i++) {
console.log(i);
if(y.length===z.length) {
if (y[i]===z[i]){
// good for now
console.log('up to now it matches');
} else {
// a letter differs
console.log('a letter differs');
areAnagrams = false;
}
}
else {
console.log(a + " has a different amount of letters than " + b);
areAnagrams = false;
}
}
if (areAnagrams) {
console.log('They ARE anagrams');
} else {
console.log('They are NOT anagrams');
}
return areAnagrams;
}
compare("mary", "arms");
A more modern solution without sorting.
function(s, t) {
if(s === t) return true
if(s.length !== t.length) return false
let count = {}
for(let letter of s)
count[letter] = (count[letter] || 0) + 1
for(let letter of t) {
if(!count[letter]) return false
else --count[letter]
}
return true;
}
function validAnagramOrNot(a, b) {
if (a.length !== b.length)
return false;
const lookup = {};
for (let i = 0; i < a.length; i++) {
let character = a[i];
lookup[character] = (lookup[character] || 0) + 1;
}
for (let i = 0; i < b.length; i++) {
let character = b[i];
if (!lookup[character]) {
return false;
} else {
lookup[character]--;
}
}
return true;
}
validAnagramOrNot("a", "b"); // false
validAnagramOrNot("aza", "zaa"); //true
Here's my contribution, I had to do this exercise for a class! I'm finally understanding how JS works, and as I was able to came up with a solution (it's not - by far - the best one, but it's ok!) I'm very happy I can share this one here, too! (although there are plenty solutions here already, but whatever :P )
function isAnagram(string1, string2) {
// first check: if the lenghts are different, not an anagram
if (string1.length != string2.length)
return false
else {
// it doesn't matter if the letters are capitalized,
// so the toLowerCase method ensures that...
string1 = string1.toLowerCase()
string2 = string2.toLowerCase()
// for each letter in the string (I could've used for each :P)
for (let i = 0; i < string1.length; i++) {
// check, for each char in string2, if they are NOT somewhere at string1
if (!string1.includes(string2.charAt(i))) {
return false
}
else {
// if all the chars are covered
// and the condition is the opposite of the previous if
if (i == (string1.length - 1))
return true
}
}
}
}
First of all, you can do the length check before the for loop, no need to do it for each character...
Also, "break" breaks the whole for loop. If you use "continue" instead of "break", it skips the current step.
That is why only the first letters are compared, after the first one it quits the for loop.
I hope this helps you.
function compare (a, b) {
y = a.split("").sort();
z = b.split("").sort();
if(y.length==z.length) {
for (i=0; i<y.length; i++) {
if (y[i]!==z[i]){
console.log(a + " and " + b + " are not anagrams!");
return false;
}
}
return true;
} else { return false;}}
compare("mary", "arms");
Make the function return false if the length between words differ and if it finds a character between the words that doesn't match.
// check if two strings are anagrams
var areAnagrams = function(a, b) {
// if length is not the same the words can't be anagrams
if (a.length != b.length) return false;
// make words comparable
a = a.split("").sort().join("");
b = b.split("").sort().join("");
// check if each character match before proceeding
for (var i = 0; i < a.length; i++) {
if ((a.charAt(i)) != (b.charAt(i))) {
return false;
}
}
// all characters match!
return true;
};
It is specially effective when one is iterating through a big dictionary array, as it compares the first letter of each "normalised" word before proceeding to compare the second letter - and so on. If one letter doesn't match, it jumps to the next word, saving a lot of time.
In a dictionary with 1140 words (not all anagrams), the whole check was done 70% faster than if using the method in the currently accepted answer.
an anagram with modern javascript that can be use in nodejs. This will take into consideration empty strings, whitespace and case-sensitivity. Basically takes an array or a single string as input. It relies on sorting the input string and then looping over the list of words and doing the same and then comparing the strings to each other. It's very efficient. A more efficient solution may be to create a trie data structure and then traversing each string in the list. looping over the two words to compare strings is slower than using the built-in string equality check.
The function does not allow the same word as the input to be considered an anagram, as it is not an anagram. ;) useful edge-case.
const input = 'alerting';
const list1 = 'triangle';
const list2 = ['', ' ', 'alerting', 'buster', 'integral', 'relating', 'no', 'fellas', 'triangle', 'chucking'];
const isAnagram = ((input, list) => {
if (typeof list === 'string') {
list = [list];
}
const anagrams = [];
const sortedInput = sortWord(input).toLowerCase();
const inputLength = sortedInput.length;
list.forEach((element, i) => {
if ( inputLength === element.length && input !== element ) {
const sortedElement = sortWord(element).toLowerCase();
if ( sortedInput === sortedElement) {
anagrams.push(element);
}
}
});
return anagrams;
})
const sortWord = ((word) => {
return word.split('').sort().join('');
});
console.log(`anagrams for ${input} are: ${isAnagram(input, list1)}.`);
console.log(`anagrams for ${input} are: ${isAnagram(input, list2)}.`);
Here is a simple algorithm:
1. Remove all unnecessary characters
2. make objects of each character
3. check to see if object length matches and character count matches - then return true
const stripChar = (str) =>
{
return str.replace(/[\W]/g,'').toLowerCase();
}
const charMap = str => {
let MAP = {};
for (let char of stripChar(str)) {
!MAP[char] ? (MAP[char] = 1) : MAP[char]++;
}
return MAP;
};
const anagram = (str1, str2) => {
if(Object.keys(charMap(str1)).length!==Object.keys(charMap(str2)).length) return false;
for(let char in charMap(str1))
{
if(charMap(str1)[char]!==charMap(str2)[char]) return false;
}
return true;
};
console.log(anagram("rail safety","!f%airy tales"));
I think this is quite easy and simple.
function checkAnagrams(str1, str2){
var newstr1 = str1.toLowerCase().split('').sort().join();
var newstr2 = str2.toLowerCase().split('').sort().join();
if(newstr1 == newstr2){
console.log("String is Anagrams");
}
else{
console.log("String is Not Anagrams");
}
}
checkAnagrams("Hello", "lolHe");
checkAnagrams("Indian", "nIndisn");
//The best code so far that checks, white space, non alphabets
//characters
//without sorting
function anagram(stringOne,stringTwo){
var newStringOne = ""
var newStringTwo = ''
for(var i=0; i<stringTwo.length; i++){
if(stringTwo[i]!= ' ' && isNaN(stringTwo[i]) == true){
newStringTwo = newStringTwo+stringTwo[i]
}
}
for(var i=0; i<stringOne.length; i++){
if(newStringTwo.toLowerCase().includes(stringOne[i].toLowerCase())){
newStringOne=newStringOne+stringOne[i].toLowerCase()
}
}
console.log(newStringOne.length, newStringTwo.length)
if(newStringOne.length==newStringTwo.length){
console.log("Anagram is === to TRUE")
}
else{console.log("Anagram is === to FALSE")}
}
anagram('ddffTTh####$', '#dfT9t#D##H$F')
function anagrams(str1,str2){
//spliting string into array
let arr1 = str1.split("");
let arr2 = str2.split("");
//verifying array lengths
if(arr1.length !== arr2.length){
return false;
}
//creating objects
let frqcounter1={};
let frqcounter2 ={};
// looping through array elements and keeping count
for(let val of arr1){
frqcounter1[val] =(frqcounter1[val] || 0) + 1;
}
for(let val of arr2){
frqcounter2[val] =(frqcounter2[val] || 0) + 1;
}
console.log(frqcounter1);
console.log(frqcounter2);
//loop for every key in first object
for(let key in frqcounter1){
//if second object does not contain same frq count
if(frqcounter2[key] !== frqcounter1[key]){
return false;
}
}
return true;
}
anagrams('anagrams','nagramas');
The fastest Algorithm
const isAnagram = (str1, str2) => {
if (str1.length !== str2.length) {
return false
}
const obj = {}
for (let i = 0; i < str1.length; i++) {
const letter = str1[i]
obj[letter] ? obj[letter] += 1 : obj[letter] = 1
}
for (let i = 0; i < str2.length; i++) {
const letter = str2[i]
if (!obj[letter]) {
return false
}
else {
obj[letter] -= 1
}
}
return true
}
console.log(isAnagram('lalalalalalalalala', 'laalallalalalalala'))
console.time('1')
isAnagram('lalalalalalalalala', 'laalallalalalalala') // about 0.050ms
console.timeEnd('1')
const anagram = (strA, strB) => {
const buildAnagram = (str) => {
const charObj = {};
for(let char of str.replace(/[^\w]/g).toLowerCase()) {
charObj[char] = charObj[char] + 1 || 1;
}
return charObj;
};
const strObjAnagramA = buildAnagram(strA);
const strObjAnagramB = buildAnagram(strB);
if(Object.keys(strObjAnagramA).length !== Object.keys(strObjAnagramB).length) {
console.log(strA + ' and ' + strB + ' is not an anagram');
return false;
}
for(let char in strObjAnagramA) {
if(strObjAnagramA[char] !== strObjAnagramB[char]) {
console.log(strA + ' and ' + strB + ' is not an anagram');
return false;
}
}
return true; } //console.log(anagram('Mary','Arms')); - false
Similar approach with filter function
const str1 = 'triangde'
const str2 = 'integral'
const st1 = str1.split('')
const st2 = str2.split('')
const item = st1.filter((v)=>!st2.includes(v))
const result = item.length === 0 ? 'Anagram' : 'Not anagram' + ' Difference - ' + item;
console.log(result)

How to check two string have same characters including special characters

I have two question
1) how can I check two shuffle string have same characters
Like I have
var str1 = "ansar##//1";
var str2 = "##//sanra1";
should return true
2) If not have same characters then which are the characters not exist in second sting
var str1 = "ansar##//123";
var str2 = "##//sanra";
Should return 123
I know I can get first question answer by
str1.length===str2.length && str1.split("").sort().join() == str2.split("").sort().join();
But not sure how to get characters not matched with second string
Consider these implementations:
1)
var str1 = "ansar##//1";
var str2 = "##//sanra1";
function first(str1, str2) {
return Array.prototype.every.call(str1, function(c) {
return str2.indexOf(c) > -1;
}, this);
}
console.log(first(str1, str2));
var str1 = "ansar##//123";
var str2 = "##//sanra";
function second() {
return Array.prototype.filter.call(str1, function(c) {
return str2.indexOf(c) === -1;
}, this).join('');
}
console.log(second(str1, str2));
Update for checking if strings contain same characters you can use ES6 Set:
const checkIfStringsContainSameCharacters = (string1, string2) => {
return new Set(string1).size === new Set(string1 + string2).size;
}
using a while loop seems a reasonable solution:
var str1 = "ansar##//1";
var str2 = "##//sanra12";
s1 = str1.split('');
s2 = str2.split('');
var i = s1.length + 1;
while (i--) {
if (s2.indexOf(s1[i]) >= 0)
s2.splice(s2.indexOf(s1[i]), 1);
}
console.log(s2)
the resulting array represents the letters of str2 not matched in str1
this will return empty string if character set in both strings is the same.
function findDiff (str1, str2)
{
var diff = '';
if (str1.length > str2.length)
{
var search = str1;
var compare = str2;
}
else
{
var search = str2;
var compare = str1;
}
for (var i = 0; i < search.length; i++)
{
var symbol = search[i];
if (compare.indexOf(symbol) === -1)
{
diff += symbol;
}
}
return(diff);
}
findDiff("ansar##//123", "##//sanra");
https://jsfiddle.net/tadaspaplauskas/pn7jnj8e/
This will return a true or false, if character in both string having the same character, and i think this is the most efficent way to do that.
a)
function hasSameCharacter(str1, str2) {
let a = Array.prototype.every.call(str1, (char) => str2.indexOf(char) > -1, this);
if (a) return Array.prototype.every.call(str2, (char2) => str1.indexOf(char2) > -1, this);
else return false;
}
console.log(hasSameCharacter(str1, str2));
b)
function hasSameCharacter(str1, str2) {
for (let i = 0; i < str1.length; i++) {
if (str2.indexOf(str1[i]) <= -1) return false;
}
for (let i = 0; i < str2.length; i++) {
if (str1.indexOf(str2[i]) <= -1) return false;
}
return true;
}
console.log(hasSameCharacter(str1, str2));
Hope this helps, happy coding :)
This code may help you to get output as per your wish.
var str1 = "ansar##//g123";
var str2 = "##//sanraD";
function strDiff(s1, s2){
var t,inter,a1,a2;
a1 = s1.split('');
a2 = s2.split('');
t = a2, a2 = a1, a1 = t;
inter = a1.filter(function (e) {
if (a2.indexOf(e) !== -1) return true;
});
for (i=0, len=inter.length; i<len; i++) {
for(var j = a1.length-1; j>=0;j--)
if (a1[j] === inter[i]) a1.splice(j, 1);
for(var k = a2.length-1; k>=0; k--)
if (a2[k] === inter[i]) a2.splice(k, 1);
}
if((a1.join('')+a2.join('')).length > 0)
return(a1.join('')+a2.join(''));
else
return "True";
}
var result = strDiff(str2,str1);
alert(result);
So I can't comment, because I don't have the ratings, but I tried Yuriy Yakym's solution (the second one, and a massive thank you Yuriy because I'd have struggled without that to work with in the beginning) and whilst it works for this example, if you add another 'a' say to str1, it won't show you that str2 doesn't actually have 3 'a's, because it's always going to reference the first appearance of the said character. In essence, you need to delete the found characters to ensure you are accounting for duplicates, or so it seems.
I developed the below from Yuriy's code to get it working for me. Please test it yourself. Happy to be disagreed with, but it seems, it will log out everything (including duplicates) that appears in str1 but doesn't appear inside str2:
const sorter = (str1, str2) => {
const arr = str1.split("");
const newArray = arr.filter((c) => {
if (str2.indexOf(c) === -1) {
return str2.indexOf(c) === -1
} else {
str2 = str2.replace(c, '');
}
})
return newArray.join("");
};
console.log(sorter(str1, str2));
function compare(str1, str2) {
if (str1.length !== str2.length) return false
let res = ''
let str2Copy = str2
for(let i = 0; i < str1.length; i++) {
for(let j = 0; j < str2Copy.length; j++) {
if(str1[i] === str2Copy[j]) {
res += str2Copy[j]
if (j === 0) {
str2Copy = str2Copy.slice(1)
} else if(j === str2Copy.length - 1) {
str2Copy = str2Copy.slice(0, str2Copy.length - 1)
} else {
str2Copy = str2Copy.slice(0, j) + str2Copy.slice(j, str2Copy.length - 1)
}
break;
}
}
}
if(res.length !== str1.length) {
return false
} else {
return true
}
}
console.log(compare('tester', 'retset'))

Longest substring in alphabetical order Javascript

Seeing all the people talking about longest substring in alphabetical order in Python, I have decided to try it in JS.
The function should look for the longest substring inside a given string, where letters are ordered alphabetically.
Here is what I have:
var s = 'azcbobobegghakl'
function substringChecker(s) {
var longestSub = "";
for (var i = 0; i < s.length; i++) {
var count = 0;
var currSub = "";
while((i+count)<=s.length){
var curr = i+count;
var next = curr+1;
var prev = curr-1;
if(curr !== s.length-1) {
if(s[curr] <= s[next]){
currSub += s[curr]
} else {
break;
}
} else {
if(s[curr]>s[prev]) {
currSub += s[curr];
}
}
count++;
}
if(currSub.length >= longestSub.length) {
longestSub = currSub;
}
};
return longestSub;
}
var result = substringChecker(s);;
console.log(result);
The funny thing it works great for all test cases I can come up with, but this one. The result should be "beggh" but it is "begg" instead. Why is the h not showing up, what am I missing?
The algorithm can be linear, I think you are overcomplicating it placing loops inside loops.
I would use something like
function substringChecker(s) {
var longestSub = "",
length = 0,
start = 0,
prev = s[0];
for (var i = 1; i <= s.length; ++i) {
if(i == s.length || s[i] < prev) {
if(length < i-start) {
longestSub = s.substring(start, i);
length = i-start;
}
start = i;
}
prev = s[i];
};
return longestSub;
}
document.write(substringChecker('azcbobobegghakl'));
first I made list of A-z
then check each letter and compare it with the next letter and save it in subString and...
function longest(str) {
//handle the case str is just one letter
if (str.length === 1) return str;
// create a list of alphabet A to Z
const alphabets = [...Array(26)].map(_ => String.fromCharCode(i++), (i = 97));
let longString = "";
let subSting = "";
for (let x = 0; x < str.length; x++) {
let char = str.charAt(x);
const nextChar = str.charAt(x + 1);
let charIndex = alphabets.findIndex(alphabet => alphabet === char);
let nextCharIndex = alphabets.findIndex(alphabet => alphabet === nextChar);
if (nextCharIndex >= charIndex) {
subSting = subSting + nextChar;
} else {
if (!subSting.length) {
subSting = subSting + char;
}
longString = subSting.length > longString.length ? subSting : longString;
subSting = "";
}
}
return longString;
}
console.log(longest("zyba"));

Categories