Hi Im using Javascript to work on an anagram problem. I am having issues comparing the 2 objects I have made out of the 2 strings that were put into the function.
The function should return true if the 2 strings have the same letters occurring the same number of times. Regardless of order in the string. You ignore the casing of the letters too, to do that I made all strings lowercase. Here is my code:
//example:
//validAnagram('', '') //true
//validAnagram('aaz', 'zza') //false
const validAnagram = (str1, str2) => {
str1 = str1.toLowerCase()
str2 = str2.toLowerCase()
const frequency1 = {}
const frequency2 = {}
//if lengths of string isnt the same automatically make it false
if(str1.length !== str2.length){
return false
}
//putting letters of the strings with their frequencies in the objects
for(let letter of str1){
if(!frequency1[letter]){
frequency1[letter] = 1
}
else {
frequency1[letter]++
}
}
for(let letter of str2){
if(!frequency2[letter]){
frequency2[letter] = 1
}
else {
frequency2[letter]++
}
}
for(let char in frequency1){
if(!(frequency2[char])){
return false
}
else if(frequency2[char] !== frequency1[char]){
console.log(char)
return false
}
else{
return true
}
}
}
First: I searched all unique characters from 2 string and saved then in array
Second: I concat 2 arrays and then using set, removed all duplicate items (characters)
Third: I loop through each character and find the occurrence of that item
forth: if occurrence matched or not, or if the character actually not exists in any of the string, can be found in the console.
const string1 = 'dafdsef dgrg tdyhjTdh drdd# dgrgrth-grth'
const string2 = '#dafdsef dgrg tdyhjtdh drdd dgrgr;thgrth'
console.log("strings matched : "+test_string(string1 , string2));
function test_string(string1 , string2){
jointArray = [...unique_char(string1.toLowerCase()), ...unique_char(string2.toLowerCase())]
neewarray = [...new Set([...jointArray])]
ok = true;
neewarray.forEach( v=> {
var re = new RegExp(v, 'g');
if(string1.match(re) && string2.match(re) ){
if( string1.match(re).length == string2.match(re).length ) {
console.log(` ${v} => matched in 2 strings`)
}
else{
ok = false;
console.log(` ${v} => not matched in 2 strings`)
}
}
else if(string1.match(re)){
ok = false;
console.log(` ${v} => not avialable in a string1 `)
}
else if(string2.match(re)){
ok = false;
console.log(` ${v} => not avialable in a string2 `)
}
})
return ok;
}
function unique_char(str1){
var str=str1;
var uniq_array=[];
for (var x=0;x < str.length;x++){
if(uniq_array.indexOf(str.charAt(x))==-1){
uniq_array.push(str[x]);
}
}
return uniq_array;
}
Related
I'm trying to figure out valid parentheses problem from leetcode using JavaScript and I couldn't figure out a plan on how to solve this problem.
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Every close bracket has a corresponding open bracket of the same type.
Example 1:
Input: s = "()"
Output: true
Example 2:
Input: s = "()[]{}"
Output: true
Example 3:
Input: s = "(]"
Output: false
My current thinking process is like this:
Split the string into an array (example: "{}" --> ["{","}", "[", "]", "(", ")"]
Loop through the array
Use the index of each characters to compare...?
Not sure after this...
Help please.
Here's a simple stack implementation:
const BRACKETS = [['(', ')'], ['[', ']'], ['{', '}']];
const OPEN = BRACKETS.reduce((a, [o, c]) => ({...a, [o]: c}), {});
const CLOSE = BRACKETS.reduce((a, [o, c]) => ({...a, [c]: o}), {});
const isBalanced = (s) => {
const stack = [];
for (const c of [...s]) {
if (c in OPEN) stack.push(c);
if (c in CLOSE && stack.pop() !== CLOSE[c]) return false;
}
return !stack.length;
};
console.log(isBalanced('{{[()]()}}'));
console.log(isBalanced('{[)}'));
I first create two lookup objects for opening and closing brackets. Then it's just a matter of looping over the characters, and:
if it's an opening bracket, push it onto the stack;
if it's a closing bracket, pop the last value off the stack and check whether it matches the closing bracket;
after everything is processed, check that the stack is empty.
const OPENING_BRACKETS = ['(', '[', '{']
const CLOSING_BRACKETS = [')', ']', '}']
const hasBalancedBrackets = text => !countUnmatchedBrackets(text)
function countUnmatchedBrackets(text) {
return [...text].filter(isBracket).reduce((stack, bracket) =>
isOpen(bracket) || !isMatch(stack.at(-1), bracket)
? /* push */ stack.concat(bracket)
: /* pop */ stack.slice(0, stack.length - 1), []).length
}
function isMatch(lastBracket, bracket) {
return OPENING_BRACKETS.some((openBracket, i) =>
lastBracket === openBracket &&
bracket === CLOSING_BRACKETS[i])
}
function isBracket(char) { return isOpen(char) || CLOSING_BRACKETS.includes(char) }
function isOpen(bracket) { return OPENING_BRACKETS.includes(bracket) }
[
[false, '[){'],
[true, 'a()a'],
[true, '{{[([a]a)a]a}}'],
[false, 'aa{a}a[aa(a](({[{a[[[()(([[a']
].forEach(([expected, input]) =>
console.assert(expected === hasBalancedBrackets(input), input))
Valid Parentheses In Javascript (Asked in many interviews. Simple and accepted solutions.)
Methods used here are string iteration and charAt and replace methods.
var isValid = function(s) {
let par ={'(' :')','{': '}', '[':']'};
for(let i=0;i<s.length;++i) {
if(s.charAt(i+1) && s.charAt(i+1)== par[s.charAt(i)]){
s = s.replace(s.charAt(i)+s.charAt(i+1),'');
i=i-2;
}
}
if(s.length){
console.log(false)
return false;
} else {
console.log(true)
return true;
}
};
console.log(isValid("()[]{}"))
const isValid = (s) => {
let stack = [];
const map = new Map([
['(', ')'],
['{', '}'],
['[', ']'],
]);
for (let i = 0; i < s.length; i++) {
if (s[i] == '(' || s[i] == '{' || s[i] == '[') {
stack.push(s[i]);
} else {
const last = stack.pop();
if (s[i] !== map.get(last)) {
return false;
}
}
}
return stack.length === 0;
};
There is a task: The field “First Name Last Name” can only consist of 2 words (first name and last name). Min length of each word is 3 characters, max 30. There is only 1 space between words.
The problem is that after the first word, when you put a space, it already returns true. Why? And how to check the 1 space in this input?
const validateInput = (value) => {
const lengthValue = value.split(' ').length
if (lengthValue !== 2) {
return false
} else {
return value.split(' ').filter(el => el.length > 3 && el.length <= 30) ?
value.search(/[A-Za-z]+(\s+[A-Za-z]+)?/gi) !== -1 ?
true :
false :
''
}
}
Use trim to remove spaces from around the words before testing
No need for else after a return. Makes it easier to read too
Why are you testing the words in the name for whitespace? That only works if the user pasted a newline or a tab, since you split on space
You have a nested ternary, why would you return an empty string there?
Also please read this for the future falsehoods programmers believe about names
const re = /[A-Za-z]{3,30}/;
const validateInput = (value) => {
const val = value.trim();
if (val === "") return false;
const arr = value.split(' ');
if (arr.length != 2) return false;
const [firstName, lastName] = arr;
return re.test(firstName) && re.test(lastName); // we could use .every here but you only have two
}
console.log(validateInput("Hans Anders"));
console.log(validateInput("Prince"));
console.log(validateInput("X Æ A-12"));
console.log(validateInput(" A "));
You can check if the no. of words are less than equal to two and the length of all the words fall within the specified range.
const message = document.querySelector("small");
document.querySelector("input").addEventListener("keyup", (e) => {
const isValid = validateInput(e.target.value);
if (isValid) {
message.textContent = "Valid input";
} else {
message.textContent = "Invalid input";
}
});
const validateInput = (input) => {
const words = input.split(" ");
return words.length <= 2 && words.every((w) => /^[A-Za-z]{3,30}$/.test(w));
};
<div>
<label>
Name:
<input type="text" />
</label>
</div>
<small>Invalid input</small>
Recently, I've been asked for the implementation of an interesting algorithm. I have a function (isValidString). It should return true if the given string is valid or not. The string pattern looks like a valid expression. My first thought was to use a regular expression, then
I've decided to collect string key occurrences in an object and check if it's even number and so on... but there are a lot other cases can be exist. Any thoughts how to implement this algorithm effectively? Thanks
Here is how it looks like:
function isValidString(string) {
}
//Patterns for the valid string:
isValidString('{([])}') //should return true
isValidString('{(([{}]))}') //should return true
isValidString('{[[()]]}') //should return true
isValidString('{[}()]}') //should return false
isValidString('{{}()]}') //should return false
isValidString('{(})[]}') //should return false
I assume that "valid" are those string whose brackets are balanced and well-formed.
You can use the following function:
const isValidString = (sample) => {
const stack = [] // This is a helper stack we will push the characters
// We start looping through the characters
for (char of sample){
// If its an opening bracket we just push it to the stack
if (['(', '[', '{'].includes(char)) {
stack.push(char)
} else {
// If we find a closing bracket we check if the previous matchs it as its opening bracket
const last = stack.pop()
// If doesnt match the previous bracket, we return false. We found a wrong formed bracket!
// If it matches, contine looping
if (
char === ')' && last !== '(' ||
char === '}' && last !== '{' ||
char === ']' && last !== '['
) return false
}
}
// If theres no characters left in the stack means that all opening brackets have been popped succesfully from the stack when we found its closing bracket
return stack.length === 0
}
console.log(isValidString('{([])}')) //should return true
console.log(isValidString('{(([{}]))}')) //should return true
console.log(isValidString('{[[()]]}')) //should return true
console.log(isValidString('{[}()]}')) //should return false
console.log(isValidString('{{}()]}')) //should return false
console.log(isValidString('{(})[]}')) //should return false
public class Solution {
public static void main(String args[]) {
Solution solution = new Solution();
String exampleInput = "[{}]";
System.out.println(" Response " + solution.isValid());
}
/**
* Returns true the string is valid, else false.
*/
public boolean isValid(String s) {
if (s == null || s.length() == 0) {
return false;
}
Map<Character,Character> startEndElements = new HashMap<>();
startEndElements.put('[',']');
startEndElements.put('{','}');
startEndElements.put('(',')');
char[] elements = s.toCharArray();
Stack<Character> store = new Stack<>();
for (char element : elements) {
if (startEndElements.containsKey(element)) {
store.push(element);
} else if (startEndElements.containsValue(element)) {
char peekElement = ' ';
if (store.isEmpty()) {
return false;
}
if (!store.isEmpty()) {
peekElement = store.peek();
}
if(isMatchingElement(peekElement, element)) {
if (!store.isEmpty()) {
store.pop();
}
} else {
return false;
}
}
}
return store.isEmpty();
}
/**
* Helper method to find if the characters form correct pair.
**/
private boolean isMatchingElement (char startElement, char endElement) {
if (startElement == '[' && endElement == ']') {
return true;
} else if (startElement == '{' && endElement == '}') {
return true;
} else if (startElement == '(' && endElement == ')') {
return true;
} else {
return false;
}
}
}
function isValidString(str){
const matches = {
"[": "]",
"{": "}",
"(": ")"
}
if(str.length % 2){
return false
}
let len = str.length / 2
str1 = str.substr(0,len)
str2 = str.substr(len,str.length).split("").reverse().join("");
return str1.split("").every((char,idx) => matches[char] == str2[idx])
}
console.log(isValidString('{([])}')) //should return true
console.log(isValidString('{(([{}]))}')) //should return true
console.log(isValidString('{[[()]]}')) //should return true
console.log(isValidString('{[}()]}')) //should return false
console.log(isValidString('{{}()]}')) //should return false
console.log(isValidString('{(})[]}')) //should return false
This question already has answers here:
Why does javascript's "in" operator return true when testing if 0 exists in an array that doesn't contain 0?
(6 answers)
Closed 3 years ago.
I'm literally stuck at solving this simple question. Anyway I found out another way to solve this but I couldn't figure out the issue with my code.
function charCout(str)
{
str = str.toLowerCase();
var f = {};
for(let i =0;i<str.length;i++)
{
if(str[i] === " ")
{
continue;
}
else{
if(str[i] in Object.keys(f))
{
f[str[i]] += 1;
}
else
{
f[str[i]] = 1;
}
}
}
return(f);
}
input: charCout("my name is Khan23")
expected output: {2: 1,3: 1,a: 2,e: 1,h: 1,i: 1,k: 1,m: 2,n: 2,s: 1,y: 1}
what i got: {2: NaN,3: NaN,a: 1,e: 1,h: 1,i: 1,k: 1,m: 1,n: 1,s: 1,y: 1}
Simply see if the property exists by type coercion like: if(f[str[i]])
function charCount(str)
{
str = str.toLowerCase();
var f = {};
for(let i =0;i<str.length;i++)
{
if(str[i] === " ")
{
continue;
}
else{
if(f[str[i]])
{
f[str[i]] += 1;
}
else
{
f[str[i]] = 1;
}
}
}
return(f);
}
console.log(charCount('the value is 0000'))
You are using the wrong to way to check if key is in object or not.
You can contract your if-else to single line using || operator.
f[str[i]] = f[str[i]] + 1 || 1
It checks whether f[str[i]] already exists or not. If str[i] is not key of f then f[str[i]] will return undefined and undefined + 1 will be NaN.
NaN is a falsy value so NaN || 1 will evaluate to 1.
If the f[str[i]] exists then it will return any number greater than 0 so it will be set to f[str[i]] + 1(incremented by one)
function charCount(str)
{
str = str.toLowerCase();
var f = {};
for(let i =0;i<str.length;i++)
{
if(str[i] !== " ")
{
f[str[i]] = f[str[i]] + 1 || 1
}
}
return(f);
}
console.log(charCount("my name is Khan23"))
Explanation:
You can also use reduce().
const charCount = str => str
.split(' ')
.join('')
.split('')
.reduce((ac,a) =>
(ac[a] = ac[a] + 1 || 1, ac),
{})
console.log(charCount("my name is Khan23"))
using Object.keys(f).includes(str[i]) instead of str[i] in Object.keys(f) is the solution
in operator primarily would work to check if Object provides a particular attribute
Mozilla doc on in and Array.prototype.includes shall help.
following variation of your function would work
function charCout(str)
{
str = str.toLowerCase();
var f = {};
for(let i =0;i<str.length;i++)
{
if(str[i] === " ")
{
continue;
}
else{
if(Object.keys(f).includes(str[i]))
{
f[str[i]] += 1;
}
else
{
f[str[i]] = 1;
}
}
}
return(f);
}
You can take advantage of String.protoype.split and Array.prototype.reduce to solve this. Check the comments in the code for details:
const charCount = s => {
//Create an array of characters found in the string (filtering out spaces)
const chars = s.split('').filter(char => char.trim());
//Use reduce to create an occurrence map - increment by 1 each time a character is encountered
return chars.reduce((accum, char) => {
accum[char] = accum[char] ? accum[char] + 1 : 1;
return accum;
}, {});
};
console.log(charCount("my name is Khan23"))
Thank you all for your helpful suggestions. i finally figured out whats wrong with my code.
inputs and outputs of my defected code is as follows:
input: charCout("my name is Khan23")
expected output: {2: 1,3: 1,a: 2,e: 1,h: 1,i: 1,k: 1,m: 2,n: 2,s: 1,y: 1}
what i got: {2: NaN,3: NaN,a: 1,e: 1,h: 1,i: 1,k: 1,m: 1,n: 1,s: 1,y: 1};
I've used "in" operator to find out whether a specific value of string is present the Object.keys(f) array. That's exactly where I went wrong.
after referring to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in i got to know "in" can't be used to filter array using value at index.
You can use str.split("") to get the list of chars and then do something like
const splitted = str.split("");
const result = {};
splitted.map(letter => result[letter] ? result[letter]++ : result[letter] = 1)
it is just an idea
I've done similar exercises to this one before and always figured it out, but I'm stuck with the silliest thing.
I'm doing the classic "get the middle character' (This function takes a string and returns an array containing the middle characters of each word. If the word is of even length then you should find the middle two characters) and I think my code should work well for all tests but the empty string one.
When an empty string "" is passed, it should return an empty array [], an even specifying to do so, it returns "".
This is my code so far:
function getMiddleChars (str) {
let empty =[];
let middle = str.length /2;
for(let i =0; i<str.length; i++){
if(str === ""){
return empty;
}else if(str.length %2 == 0){
return str.slice(middle -1, middle +1);
}
}
return str.charAt(middle);
}
returns [] when passed "":
AssertionError: expected '' to deeply equal []
Could anyone give me a hand? Thanks in advance.
EDITED:
function getMiddleChars (str) {
let solution = [];
let middle = str.length /2;
if(str === ""){
return [];
} if(str.length %2 === 0){
return solution.push(str.slice(middle -1, middle +1));
} else {
return solution.push(str.charAt(middle));
}
}
Still won't work. I was pretty sure I could figure this out and I'm lost now.
Split the string to words, iterate with Array.map(), and return the middle characters for each word:
function getMiddleChars(str) {
return str ? str.split(/\s+/).map((word) => {
const middle = (word.length - 1) / 2;
return word.substring(Math.floor(middle), Math.ceil(middle) + 1);
}) : [];
}
console.log(getMiddleChars('cats')); // ["a", "t"]
console.log(getMiddleChars('cat')); // ["a"]
console.log(getMiddleChars('a')); // ["a"]
console.log(getMiddleChars('hello world')); // ["l", 'r']
console.log(getMiddleChars('')); // []
You could do this as the first step of your function:
if(str === "")
{
return [];
}