Simpler way to write the scramble function - javascript

I want a simpler way for the function scramble(str1,str2) so that if a portion of str1 can be arranged to match str2 . Note that all the letters to be used are lowercase . I used the following code and it worked , but can anyone show me a simpler way .
function scramble(str1,str2){
str2 = str2.split('');
str1 = str1.split('');
let arr = [] , condition ;
arr.length = str2.length;
for(let i =0;i<str2.length;i++){
for(let a= 0 ;a<str1.length;a++){
if(str2[i] == str1[a]){
str1[a] = '';
arr[i] = 'true'
break;
}
}
}
for(let i = 0;i<arr.length;i++){
if(arr[i] == undefined){
return false
}
}
return true
}
console.log(scramble('rkqodlw','world')) //true;
console.log(scramble('cedewaraaossoqqyt','codewars'))//true
console.log(scramble('katas','steak')) //false
console.log(scramble('scriptjava','javascript'))//true
console.log(scramble('scriptingjava','javascript'))//true
console.log(scramble('scriptsjava','javascripts')//true
console.log(scramble('jscripts','javascript')) //false
console.log(scramble('aabbcamaomsccdd','commas')) //true

You could make count all chars in str1, then go over str2, decrement the count and return false if it reaches 0:
const count = {};
for(const char of str1)
count[char] = (count[char] || 0) + 1;
for(const char of str2)
if(!count[char]--) return false;
return true;

This problem is a version of generic issue of checking if one set of elements is a subset of another.
The base step to solve this task is to take first element of set1 and check if it is present in set2. If it isn't we return false. If it is we check the next element with set2 minus the matched element;
The base case is when we have an empty set (because empty set is a subset of any set)
function check(str1, str2) {
if (str2.length === 0) {
return true;
}
const [first, ...rest] = str1;
const idx = str2.indexOf(first);
if (idx !== -1) {
const str2Rest = [...str2.slice(0, idx), ...str2.slice(idx+1)];
return check(rest, str2Rest);
}
return true;
}
You can also first sort the strings and then go through both knowing that the matched char might be only on the current position or at the higher index
function sorted(str1, str2) {
str1 = [...str1].sort();
str2 = [...str2].sort();
let s1 = 0;
let s2 = 0;
while (s1 < str1.length && s2 < str2.length) {
if(str1[s1] === str2[s2]) {
s1 += 1;
}
s2 += 1;
}
return s1 === str1.length
}
The most performant solution for unsorted items is to go through the chars of both in the worst case only one:
function performant(str1, str2) {
const stash = {};
let s1 = 0;
let s2 = 0;
while (s1 < str1.length && s2 < str2.length) {
const ch1 = str[s1];
const ch2 = str[s2];
if(ch1 === ch2) {
s1 += 1;
s2 += 1;
continue;
}
if (stash[ch1]) {
s1 += 1;
stash[ch1] -= 1;
}
stash[ch2] = (stash[ch2] | 0) + 1;
s2 += 1;
}
return s1 === str1.length;
}

Related

Changing the value of an index inside an array

I'm stuck with this problem where I need to eliminate a letter from each of the array values and change the first letter if it is in index 0. My current approach is this:
function capital(arr, char){
let str = "";
let result = "";
for (let i = 0; i < arr.length; i++){
str = arr[i] + (i < arr.length - 1 ? ",": "");;
for (let j = 0; j < str.length; j++){
if (str[j] === char){
result += "";
if (str[j] === char){
result += (j === 0? "A": "");
}
else {
result += str[j];
}
}
}
console.log(result);
}
capital(["doritos","sandking","bandana", "demand"], "d");
The program should eliminate each occurrence of letter d found in the strings and change the index 0 to letter A if the d is in index 0.
The current result is
Aoritos,sanking,banana,Aeman
but it should look like
Aritos,sanking,banana,Aman
The requirement does not allow any use of built in functions, and the actual program requires the letters to be case insensitive, but I can work on it by substituting codes and adding couple if elses, I just need help with the changing the index 0 condition. Any help would be appreciated, thank you!
You can check if your input char is at first index str.indexOf(char) then simply add prefix "A" to your string without first char i.e str.substring(1)
function capital(arr, char) {
let str = "";
let result = "";
for (let i = 0; i < arr.length; i++) {
str = arr[i];
if(str.indexOf(char) === 0) {
result = 'A' + str.substring(1);
}else {
result = str;
}
console.log(result);
}
}
capital(["doritos", "sandking", "bandana", "demand"], "d");
this logic may help you
function capital(arr, char) {
return arr.map(e => {
let isFirst = false;
if (e[0] == "d") isFirst = true;
e = e.replace(new RegExp(char, 'ig'), '');
if (isFirst)
e = e.replace(e.charAt(0), "A");
return e;
});
}
console.log(capital(["doritos", "sandking", "bandana", "demand"], 'd'))
You can iterate through each letter of your word and update the first letter if it is matched with passed letter and at 0 index, for other index if it doesn't match with passed letter add to your result.
const capitalize = ch => {
const letter = ch.charCodeAt(0);
if(letter >= 97 && letter <= 122) {
return String.fromCharCode(letter - 32);
}
return ch;
}
const capital = (words, ch) => {
let result = '';
for(let i = 0; i < words.length; i++) {
let newWord = '';
for(let j = 0; j < words[i].length; j++) {
if(capitalize(words[i][j]) === capitalize(ch) && j === 0) {
newWord = 'A';
}
if(capitalize(words[i][j]) !== capitalize(ch)) {
newWord += words[i][j];
}
}
result += newWord;
if(i < words.length - 1 ) {
result += ',';
}
}
return result;
}
const result = capital(["doritos","sandking","bandana", "demand", "sandDking"], "d");
console.log(result);

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 ignore spaces in string indexes and start with a capital letter on each word in a sentence

Basically, I have this code, where I want to change a given string to wEiRd CaSe, alternate between indexes, for example:
Starting from index 0 I want the letter to be capital, and then when the index got to an odd number, like 1, 3, 5, etc... I want to change it to uppercase.
So:
Stackoverflow should be StAcKoVeRfLoW, But I also want to work with strings, strings like this
This is a test should be: ThIs Is A TeSt
But my function returns : ThIs iS A TeSt
Here's my code:
"use strict";
var weirdCase = function(string) {
var characters = string.split("");
characters.forEach(function(value, index, characters) {
// If the index is even
if (index % 2 == 0) {
characters[index] = value.toUpperCase();
} else {
characters[index] = value.toLowerCase();
}
});
return characters.join("");
}
My question might be a bit misleading, I wanted to be wEiRd Case but also the first letter of the words to be capital, So I did this:
function toWeirdCase(string){
return string.split(' ').map(function(word){
return word.split('').map(function(letter, index){
return index % 2 == 0 ? letter.toUpperCase() : letter.toLowerCase()
}).join('');
}).join(' ');
}
Hope this helps someone
You can add another variable charIndex which you increase manually only if the value is no space. charIndex will represent the indexes for your string like it has no spaces in it.
"use strict";
var weirdCase = function(string) {
var characters = string.split("");
var charIndex = 0;
characters.forEach(function(value, index, characters) {
//Exclude spaces
if (value === " ") {
return;
}
// If the index is even
if (charIndex % 2 == 0) {
characters[index] = value.toUpperCase();
} else {
characters[index] = value.toLowerCase();
}
//Increment charIndex
charIndex += 1;
});
return characters.join("");
}
Should be as simple as this:
function WeIrDcAsE(string) {
let isUpperCase = true;
let result = '';
for (let character of string) {
if (isUpperCase) {
result += character.toUpperCase();
} else {
result += character.toLowerCase();
}
if (character.match(/[a-zA-Z]/)) {
isUpperCase = !isUpperCase;
} else {
isUpperCase = true;
}
}
return result;
}
console.log(WeIrDcAsE("This is a test!"));
In a much more simpler way...
a = "This is a test"
b = a.split('')
counter = 0
c = b.map(function(c) {
if (c === ' ') return c
if ((counter % 2) === 0) {
counter++
return c.toUpperCase()
}
counter++
return c.toLowerCase()
})
console.log(c.join(''))
This code can be simplified a lot, I think.
var weirdCase = function(str){
var upper = false;
for (var i = 0; i < str.length; i++){
if (str[i] != ' '){
if (upper){
str[i] = character.toUpperCase();
}else{
str[i] = character.toLowerCase();
}
upper = !upper;
}
}
I would do as follows;
var str = "this is a test",
result = str.split(" ")
.map(s => [].reduce
.call(s, (p,c,i) => p += i & 1 ? c.toLowerCase()
: c.toUpperCase(),""))
.join(" ");
console.log(result);
var string= 'Stackoverflow';
for (var i=0; i<string.length; i+=2)
string= string.substr(0,i) + string[i].toUpperCase() + string.substr(i+1);
Nev er mid, scratch this: I need to read more carefully, sorry.

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