Accounting for tiebreakers in the longest of three words array - javascript

function getLongestOfThreeWords(word1, word2, word3) {
word1 = word1.split(' ');
word2 = word2.split(' ');
word3 = word3.split(' ');
var newArr = word1.concat(word2,word3);
var LongestWord = [];
var LongestWordLength = 0;
for(var i=0; i<newArr.length; i++) {
if(newArr[i].length > LongestWordLength) {
longestWord = newArr[i];
longestWordLength = newArr[i].length;
}
}
return longestWord;
}
var output = getLongestOfThreeWords('these', 'three', 'words');
console.log(output); // --> 'these'
Got a problem I can't seem to figure out, for a longest of three words function -
"If there is a tie, it should return the first word in the tie."
Presently I'm only returning 'words', when 'these should be returned. This doesn't make sense to me because longestWordLength = newArr[i].length; Any help on this?

function getLongestOfThreeWords(word1, word2, word3) {
if(word1.length >= word2.length && word3.length) {
return word1;
} else if (word2.length > word3.length && word1.length) {
return word2;
} else {
return word3;
}
}
var output = getLongestOfThreeWords('these', 'three', 'words');
console.log(output); // --> 'these'

Great you figured out a solution.
You current solution though still is limited to three arguments only, if you want something more flexible use Rest Parameters
const getLongest = (...words) => words.sort((a, b) => b.length - a.length)[0];
console.log(getLongest('these', 'words', 'three')); // these
console.log(getLongest('super')); // super
console.log(getLongest('nice', 'and', 'super', 'flexible')); // flexible

Your first approach:
Put words in newArr
Iterate over the array, if the current item's length is greater than longestWordLength, do the updates
Note: you're updating different variables that you defined at first
function getLongestOfThreeWords(word1, word2, word3) {
const newArr = [word1, word2, word3];
let longestWord = undefined;
let longestWordLength = 0;
for(let i = 0; i < newArr.length; i++) {
if(newArr[i].length > longestWordLength) {
longestWord = newArr[i];
longestWordLength = newArr[i].length;
}
}
return longestWord;
}
const output = getLongestOfThreeWords('these', 'three', 'words');
console.log(output);
Your other approach with the correct conditions:
function getLongestOfThreeWords(word1, word2, word3) {
if(word1.length >= word2.length && word1.length >= word3.length) {
return word1;
} else if (word2.length >= word3.length) {
return word2;
} else {
return word3;
}
}
const output = getLongestOfThreeWords('these', 'three', 'words');
console.log(output);

Related

I'm solving Leetcode problem: 14 using Javascript

I sorted the elements and comparing the first and last string to check the common prefixes. It works for most of the cases, but not for the input ["dog","racecar","car"]. The expected output is "", but what I'm getting is "c" (The "r" in "car" and "r" in "racecar"). I can tell the code to remove the last char, but this will break the other cases such as ["car", "car", "car"]. Not sure what am I missing. Any insights would help me improve.
Thanks
var longestCommonPrefix = function(strs) {
let count=0
const sortedString = strs.sort()
const firstString = sortedString[0]
const lastString = sortedString[sortedString.length-1]
for(let i=0; i< firstString.length; i++) {
if(firstString.charAt(i) === lastString.charAt(i)) {
count++
}
}
console.log(firstString.substring(0, count))
};
longestCommonPrefix(
["dog","racecar","car"])
You need to break out of the loop as soon as a match is not found. Otherwise, for example, ra and ca match on the second index, the a - which is undesirable.
var longestCommonPrefix = function(strs) {
let count = 0
const sortedString = strs.sort()
const firstString = sortedString[0]
const lastString = sortedString[sortedString.length - 1]
for (let i = 0; i < firstString.length; i++) {
if (firstString.charAt(i) === lastString.charAt(i)) {
count++
} else {
break;
}
}
console.log(firstString.substring(0, count))
};
longestCommonPrefix(
["dog", "racecar", "car"])
or, refactored a bit
const longestCommonPrefix = (strs) => {
strs.sort();
const firstString = strs[0];
const lastString = strs[strs.length - 1];
let prefixSoFar = '';
for (let i = 0; i < firstString.length; i++) {
if (firstString[i] === lastString[i]) {
prefixSoFar += firstString[i];
} else {
return prefixSoFar;
}
}
return prefixSoFar;
};
console.log(longestCommonPrefix(["dog", "racecar", "car"]));

How to get the longest string in array without similar like values?

I have 2 arrays.
1: [a, ab, abc, abcde]
2: [a, ab, abc, abcde, abcdefe, axde]
in the first array, I used this code to get the longest line.
function longestChain(words) {
// Write your code here
var xintTOstring = "";
var result = 0;
for (var x = 0; x < words.length; x++){
xintTOstring = words[x].toString();
if (xintTOstring.length > result) {
result = xintTOstring.length;
}
}
return result;
}
but then in the second array, the longest is "axde". because the abcde in that array cannot be the longest because it has an equal like value.
I try this code but did not get the expected result. and also the longest line is the abcdefer.
question: how can I get the longest line and check if it is valued like equal in the string. I tried this code but did not get the right output.
function longestChain(words) {
// Write your code here
var xintTOstring = "";
var result = 0;
for (var x = 0; x < words.length; x++){
xintTOstring = words[x].toString();
if (!words[x].toString().inclcudes(xintTOstring)) {
if (xintTOstring.length > result) {
result = xintTOstring.length;
}
}
}
return result;
}
regards
function equalLike(word) {
// should the equality be checked within the array or in global stream?
}
function longestChain(words) {
return words.reduce((longest,word) => longest = longest.length > equalLike(word).length ?
longest : word,'');
}
the longest word acts as the accumulator.
If I understand correctly, each call to longest word should return the longest word not yet found. Go through each list, keep object of longest words, check against that object, and check substrings against keys
const longestWords = {};
const longestChain = function(words) {
let longestInList = "";
words.forEach(function(word) {
if (validLongestWord(word) && word.length > longestInList.length) {
longestInList = word;
}
});
longestWords[longestInList] = longestInList.length; //maybe handy for sorting later
return longestInList;
}
const validLongestWord = function(word) {
if(longestWords[word]) return false;
return !Object.keys(longestWords).some(key=>key.indexOf(word) >=0);
}
console.log(longestChain(["a", "ab", "abc", "abcde", "abcdefe", "axde"])); //abcdefe
console.log(longestChain(["a", "ab", "abc", "abcde", "abcdefe", "axde"])); //axde
console.log(longestChain(["a", "ab", "abc", "abcde", "abcdefe", "axde"])); //none
I believe this is the problem that the OP is trying to solve using JavaScript:
Longest Character Removal Chain
and
Interview Questions - String Chain
Anyone please feel welcome to edit this answer to provide a solution for the question asked.
var StackOverFlow;
(function(StackOverFlow) {
var LongestChain = (function() {
function LongestChain() {}
LongestChain.main = function(args) {
// Array of words
var words = ["a", "ab", "abc", "abcdefe", "axde"];
console.info(
"Longest Chain Length : " + LongestChain.longest_chain(words)
);
};
LongestChain.longest_chain = function(w) {
if (null == w || w.length < 1) {
return 0;
}
var maxChainLen = 0;
var words = w.slice(0).slice(0);
var wordToLongestChain = {};
for (var index7809 = 0; index7809 < w.length; index7809++) {
var word = w[index7809];
{
if (maxChainLen > word.length) {
continue;
}
var curChainLen =
LongestChain.find_chain_len(word, words, wordToLongestChain) + 1;
/* put */ wordToLongestChain[word] = curChainLen;
maxChainLen = Math.max(maxChainLen, curChainLen);
}
}
return maxChainLen;
};
LongestChain.find_chain_len = function(word, words, wordToLongestChain) {
var curChainLen = 0;
for (var i = 0; i < word.length; i++) {
var nextWord = word.substring(0, i) + word.substring(i + 1);
if (words.indexOf(nextWord) >= 0) {
if (wordToLongestChain.hasOwnProperty(nextWord)) {
curChainLen = Math.max(
curChainLen,
/* get */ (function(m, k) {
return m[k] ? m[k] : null;
})(wordToLongestChain, nextWord)
);
} else {
var nextWordChainLen = LongestChain.find_chain_len(
nextWord,
words,
wordToLongestChain
);
curChainLen = Math.max(curChainLen, nextWordChainLen + 1);
}
}
}
return curChainLen;
};
return LongestChain;
})();
StackOverFlow.LongestChain = LongestChain;
LongestChain["__class"] = "StackOverFlow.LongestChain";
})(StackOverFlow || (StackOverFlow = {}));
StackOverFlow.LongestChain.main(null);

JS How to for palindrome [duplicate]

This question already has answers here:
Palindrome check in Javascript
(45 answers)
Closed 4 years ago.
The question I have been given is this;
create a function that takes an array of words and returns an array containing only the palindromes.
A palindrome is a word that is spelled the same way backwards.
E.g. ['foo', 'racecar', 'pineapple', 'porcupine', 'pineenip'] => ['racecar', 'pineenip']
This is the code that I create;
let arr = []
let str = words.slice(0)
let pal = str.toString().split("").reverse().join("")
console.log(pal);
for (let i = 0; i < words.length; i++) {
for (let k = 0; k < pal.length; k++) {
if (words[i] == pal[k]) {
arr.push(words[i])
}
}
}
return arr
}
This is the test that my code is run against;
describe("findPalindromes", () => {
it("returns [] when passed []", () => {
expect(findPalindromes([])).to.eql([]);
});
it("identifies a palindrom", () => {
expect(findPalindromes(["racecar"])).to.eql(["racecar"]);
});
it("ignores non-palindromes", () => {
expect(findPalindromes(["pineapple", "racecar", "pony"])).to.eql([
"racecar"
]);
});
it("returns [] when passed no palindromes", () => {
expect(findPalindromes(["pineapple", "watermelon", "pony"])).to.eql([]);
});
});
Does anyone have any any suggestion of how to make my code work?
This is the simplest function that returns true or false if the str is a palindrome or not.
I would use this in combination with the filter function to filter on all palindromes. Like this
function checkPalindrom(str) { //function that checks if palindrome or not
return str == str.split('').reverse().join('');
}
const result = words.filter(word => checkPalindrom(word)); //filter function that filters array to only keep palindromes
Without giving spoilers to the answer (this is a common interview question) a clean approach would be as follows:
Define a function isPalindrome(string): boolean
Use the filter property available on the Array prototype to return an array of only palindromes e.g. inputArray.filter(isPalindrome)
Both can be unit tested separately, for example:
You could define an array of inputs and expected outputs for isPalindrome [{ input: "racecar", expectedOutput: true}, {input: "pineapple", expectedOutput: false}, ...] and loop over each test case.
function isPalindrome(word) {
const firstHalf = word.slice(0, Math.ceil(word.length/2));
const secondHalfReversed = word.slice(Math.floor(word.length/2)).split('').reverse().join('');
return firstHalf === secondHalfReversed;
}
function getPalindromesFromArray(arr) {
return arr.filter(isPalindrome);
}
const wordsArr = ['foo', 'racecar', 'pineapple', 'porcupine', 'pineenip'];
console.log(getPalindromesFromArray(wordsArr));
using for loop and filter
let arr = ["foo", "racecar", "pineapple", "porcupine", "pineenip",'pap','aaaa'];
let palindromes = arr.filter(w => {
let len = w.length;
for (let i = 0; i < len / 2; i++) {
if (w[i] == w[len - i - 1]) {
return true;
} else {
return false;
}
}
});
console.log(palindromes)
To solve that first I would create an isPalindrome function like this:
function isPalindrome(word) {
palindromeWord = ''
for(var i = word.length - 1; i >= 0; i--) {
palindromeWord += word.charAt(i)
}
return palindromeWord === word
}
and then I would check for each word inside the array like this:
let arr = ['foo', 'racecar', 'pineapple', 'porcupine', 'pineenip']
let palindromeArr = []
arr.forEach(word => {
if (isPalindrome(word)) {
palindromeArr.push(word)
}
})
console.log(palindromeArr)
What you have is good, however when you did
var pal = str.toString().split("").reverse().join("")
You changed from an array to a string, then you went into the loop with the string, so pal[k] gave a character and not a word.
To change pal back to an array of strings, split it again, use
var pal = str.toString().split("").reverse().join("").split(",");
var words = ['foo', 'racecar', 'pineapple', 'porcupine', 'pineenip'];
var arr = [];
var str = words.slice(0);
var pal = str.toString().split("").reverse().join("").split(",");
console.log(pal);
for (let i = 0; i < words.length; i++) {
for (let k = 0; k < pal.length; k++) {
if (words[i] == pal[k]) {
arr.push(words[i])
}
}
}
console.log(arr);

Checking if the characters in a string are all unique

I am trying to solve this problem using JS by just using an array.
var str = 'abcdefgh';
for (i = 0; i < 255; i++) {
arr[i] = false;
}
function check() {
for (i = 0; i < str.length; i++) {
if (arr[str.charCodeAt(i)] == true) {
return false;
}
arr[str.charCodeAt(i)] = true;
}
return true;
}
I am initializing an array of fixed size 256 to have the boolean value false.
Then i am setting the value for the corresponding ASCII index to true for characters in the string. And if i find the same character again, i am returning false.
While running the program, i am getting false returned even if the string doesn't have any duplicate characters.
Fill a Set with all characters and compare its size to the string's length:
function isUnique(str) {
return new Set(str).size == str.length;
}
console.log(isUnique('abc')); // true
console.log(isUnique('abcabc')); // false
Use object for faster result
function is_unique(str) {
var obj = {};
for (var z = 0; z < str.length; ++z) {
var ch = str[z];
if (obj[ch]) return false;
obj[ch] = true;
}
return true;
}
console.log(is_unique("abcdefgh")); // true
console.log(is_unique("aa")); // false
use .match() function for each of the character. calculate occurrences using length. Guess thats it.
(str.match(/yourChar/g) || []).length
We can also try using indexOf and lastIndexOf method:
function stringIsUnique(input) {
for (i = 0; i < input.length; i++) {
if (input.indexOf(input[i]) !== input.lastIndexOf(input[i])) {
return false;
}
}
return true;
}
You are using arr[str.charCodeAt(i)] which is wrong.
It should be arr[str[i].charCodeAt(0)]
var arr = [];
var str="abcdefgh";
for (i=0;i<255;i++){
arr[i]=false;
}
function check(){
for (i=0;i<str.length;i++){
if (arr[str[i].charCodeAt(0)]==true){
return false;
}
arr[str[i].charCodeAt(0)]=true;
}
console.log(arr);
return true;
}
check();
Time complexity = O(n)
Space complexity = O(n)
const isUnique = (str) => {
let charCount = {};
for(let i = 0; i < str.length; i++) {
if(charCount[str[i]]){
return false;
}
charCount[str[i]] = true;
}
return true;
}
const isUniqueCheekyVersion = (str) => {
return new Set(str).size === str.length;
}
Solution 3:
Transform string to chars array, sort them and then loop through them to check the adjacent elements, if there is a match return false else true
Solution 4:
It's similar to Solution 1 except that we use a Set data structure which is introduced in recent versions of javascript
// no additional Data structure is required. we can use naive solution
// Time Complexity:O(n^2)
function isUnique(str) {
for (let i = 0; i < str.length; i++) {
for (let j = 1 + i; j < str.length; j++) {
if (str[i] === str[j]) {
return false;
}
}
}
return true;
}
// if you can use additional Data structure
// Time Complexity:O(n)
function isUniqueSecondMethos(str) {
let dup_str = new Set();
for (let i = 0; i < str.length; i++) {
if (dup_str.has(str[i])) {
return false;
}
dup_str.add(str[i]);
}
return true;
}
console.log(isUniqueSecondMethos('hello'));
Use an object as a mapper
function uniqueCharacterString(inputString) {
const characterMap = {};
let areCharactersUnique = true;
inputString.trim().split("").map((ch)=>{
if(characterMap[ch]===undefined) {
characterMap[ch] = 1;
} else {
areCharactersUnique = false;
}
})
return areCharactersUnique;
}
Algo
*1. step -first string is ->stack *
*2.step-string covert to CharArray *
3. step - use iteration in array ['s','t','a','c','k']
4. step - if(beginElement !== nextElement){return true}else{return false}
Implement code
function uniqueChars(string){
var charArray = Array.from(string) //convert charArray
for(var i=0;i<charArray.length;i++){
if(charArray[i] !== charArray[i+1]){
return true
}
else{
return false
}
}
}
var string ="stack"
console.log(uniqueChars(string))
Time complexity
O(nlogn)
Algo
Counting frequency of alphabets. e.g. 'Mozilla' will returns Object{ M: 1, o: 1, z: 1, i: 1, l: 2, a: 1 }. Note that, the bitwise NOT operator (~) on -~undefined is 1, -~1 is 2, -~2 is 3 etc.
Return true when all occurrences appear only once.
Implement code
var isUnique = (str) => {
const hash = {};
for (const key of str) {
hash[key] = -~hash[key];
}
return Object.values(hash).every((t) => t === 1);
};
console.log(isUnique('Mozilla'));
console.log(isUnique('Firefox'));
Another alternative could be:
var isUnique = (str) => {
const hash = {};
for (const i in str) {
if (hash[str[i]]) return false;
hash[str[i]] = true;
}
return true;
};
console.log(isUnique('Mozilla'));
console.log(isUnique('Firefox'));
To make efficient one, you can use simple hash map
let isUnique = (s) => {
let ar = [...s];
let check = {};
for (let a of ar) {
if (!check[a]) {
check[a] = 1;
} else {
return false
}
}
return true;
}
alert("isUnique : "+isUnique("kailu"));
Time complexity & Space complexity
using ES6
let isUnique = (s)=>{
return new Set([...s]).size == s.length;
}
console.log("using ES6 : ",isUnique("kailu"));
We can use split method of string:
const checkString = (str) => {
let isUniq = true;
for (let i = 0; i < str.length; i++) {
if (str.split(str[i]).length > 2) {
isUniq = false;
break;
}
}
return isUniq;
};
console.log(checkString("abcdefgh")); //true
console.log(checkString("aa")); //false

JavaScript anagram comparison

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)

Categories

Resources