Remove contents between parentheses in Javascript - javascript

Create a function that accepts a string as input, removes all content between parentheses, and returns the modified string. If the amount of left and right parentheses doesn't match, return empty string
I have to create a function that removes all content between parentheses and returns the string without it.
For example, this input 12(3(45))67(8)9 will return this output 12679.
If the number of parentheses isn't correct return an empty string.
This is my approach:
function removeContent(str) {
let leftP = 0, rightP = 0;
// wrong number of parentheses scenario
for( let i = 0; i < str.length; i++) {
if(str[i] === '(' ) leftP++;
if(str[i] === ')' ) rightP++;
}
if( leftP !== rightP) return "";
// remove the content otherwise
}
console.log(removeContent('12(3(45))67(8)9'));
Don't know how to do the combination between pairing parentheses and remove the content.

An easy way to do this is to keep track of bracket count, and then output letters only when the bracket count is equal to 0.
At the end, if the bracket count is not zero, you can also tell it to return the empty string as requested..
eg..
function removeContent(string) {
let bracketCount = 0;
let output = '';
for (const letter of string) {
if (letter === '(') bracketCount += 1
else if (letter === ')') bracketCount -= 1
else if (bracketCount === 0) output += letter;
}
return bracketCount === 0 ? output : '';
}
console.log(removeContent('12(3(45))67(8)9'));
console.log(removeContent('12(345))67(8)9'));
console.log(removeContent('1(2)(3)45(7)8(((9)))77'));

do a find replace with regular expression /\(+[\d\(]*\)+/g

Related

The Hashtag Generator. trying to pick the error in my code

There are two codes for the same problems the first work and the second doesn't work, even though they both get the same result, why the second isn't correct?
function generateHashtag(str) {
if (str.length >= 140 || str.length == 0) return false;
else {
let arr = str.split(" ");
for (let i = 0; i < arr.length; i++) {
if (arr[i] == "") arr.splice(i, 1);
}
for (let i = 0; i < arr.length; i++) {
arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
}
return "#" + arr.join("");
}
}
function generateHashtag(str) {
regex = /\b#/gi;
if (str.length >= 140 || str.length == 0) return false;
let res = str.replace(/\b\w/gim, (c) => c.toUpperCase());
let res2 = res.replace(/\s/g, "");
return "#" + res2;
}
this is the problem :
The marketing team is spending way too much time typing in hashtags.
Let's help them with our own Hashtag Generator!
Here's the deal:
It must start with a hashtag (#).
All words must have their first letter capitalized.
If the final result is longer than 140 chars it must return false.
If the input or the result is an empty string it must return false
The difference in implementation is that for the first function you split on a space, remove the empty entries and then replace the first char of the strings returned by the splitting.
But in the second function, you replace \b\w with an uppercase char. The issue is that the \b\w can match on more places than only at the start of a word.
You could write the second function asserting either the start of the string or match a whitespace character (?:^|\s)\w
You can also remove the /i flag as \w also matches lowercase chars (Or use [a-z] instead)
Note that you are not taking this rule into account, as you are checking this at the start of the function, but at the end you are removing spaces which can cause the total length of the string after the replacement being under 140.
If the input or the result is an empty string it must return false
For that you could check the length of the result instead.
function generateHashtag(str) {
if (str.trim() === "" || str.charAt(0) === "#") return false
const result = "#" + str
.replace(/(?:^|\s)\w/gm, c => c.toUpperCase())
.replace(/\s/g, "");
if (result === "" || result.length > 140) return false
return result;
}
const strings = [
"#CodeWars",
"this is a te$s#t",
"this is a te$s#t abcd abcd abcd abcd abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdab",
"this is a te$s#t abcd abcd abcd abcd abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdab dabcdabcdabcdabcdabcdabcdab",
"a",
"$",
"'#CodeWars'"
];
strings.forEach(s => console.log(generateHashtag(s)))
You can use
function generateHashtag (str) {
if (str === undefined || str.length === 0) return false;
str = (str.match(/\w+/g) || ['']).map(x => x.charAt(0).toUpperCase() + x.slice(1)).join("")
if (str.length == 0 || str.length > 139) { return false; }
else return "#" + str;
}
That is
if (str === undefined || str.length === 0) return false; returns false when the string is empty or undefined
str = (str.match(/\w+/g) || ['']).map(x => x.charAt(0).toUpperCase() + x.slice(1)).join("") extracts all words, capitalizes them, and joins into a single string
if (str.length == 0 || str.length > 139) { return false; } returns false if the result is empty or equals 140 or more
else return "#" + str; - returns the result as a hashtag with # prepended to the str.

How to check for valid braces in javascript, programming problem?

have been struggling for the last couple of days with the following problem from codewars:
Write a function that takes a string of braces, and determines if the order of the braces is valid. It should return  true  if the string is valid, and  false  if it's invalid.
All input strings will be nonempty, and will only consist of parentheses, brackets and curly braces:  ()[]{} .
What is considered Valid?
A string of braces is considered valid if all braces are matched with the correct brace.
Examples
"(){}[]" => True
"([{}])" => True
"(}" => False
"[(])" => False
"[({})](]" => False
So I'm really stuck with the code for this one, and this is what I have up to this point:
function validBraces(braces){
let opening = [ '(', '[', '{']
let closing = [ ')', ']', '}']
let count = 0
const left = []
const right = []
// I generate left and right arrays, left w/the opening braces from the input, right w/ the closing
for (let i = 0; i < braces.length; i++) {
if (opening.includes(braces[i])) {
left.push(braces[i])
} else if (closing.includes(braces[i])) {
right.push(braces[i])
}
}
if (braces.length % 2 !== 0) {
return false
}
// I know there's no point in doing this but at one point I thought I was finishing the program and thought I would 'optimize it' to exit early, probably this is dumb haha.
if (left.length !== right.length) {
return false
}
// The juicy (not juicy) part where I check if the braces make sense
for (let i = 0; i < left.length; i++) {
// If the list are made up of braces like ()[]{} add one to counter
if (opening.indexOf(left[i]) === closing.indexOf(right[i])) {
count += 1
} else // If left and right are mirrored add one to the counter
if (opening.indexOf(left[i]) === closing.indexOf(right.reverse()[i])) {
count += 1
}
}
//If the counter makes sense return true
if (count === braces.length / 2) {
return true
} else { return false}
}
console.log(validBraces( "()" )) //true
console.log(validBraces("([])")) //true
console.log(validBraces( "[(])" )) //false
console.log(validBraces( "[(})" )) //false
console.log(validBraces( "[([[]])]" )) //true
Some comments: I know I'm still not checking for this example ([])() but I thought of breaking this up into two smaller checks in some way.
Thank you if you read up to this point. I would appreciate guidance in some way, though I don't want the problem solved for me. I'm probably overcomplicating this in some way since its a 6kyu problem, if so a tip on how to approach it more cleverly would be very much appreciated.
Thank you in advance! :pray: :pray:
Hell yeah!! I'm very happy to finally reach to the solution myself using some of the hints given to me here:
function validBraces(braces){
let opening = [ '(', '[', '{']
let closing = [ ')', ']', '}']
let arr = []
//console.log(closing.indexOf(braces[")"]) === opening.indexOf(arr[")"]))
for (let i = 0; i < braces.length; i++) {
if (opening.includes(braces[i])) {
arr.push(braces[i])
} else
if (closing.indexOf(braces[i]) === opening.indexOf(arr[arr.length - 1])) {
arr.pop()
} else return false
} return arr.length === 0;
}
I was clearly overthinking it in the first place haha. Thanks for everyone that helped!
As Dave suggested, using a stack, I've wrote the code for it:
var leftBraces="([{";
var rightBraces=")]}";
function checkBraces(braces) {
var ok=true;
var stack=[];
for(var i=0; i<braces.length && ok; i++) {
var brace=braces[i];
if(leftBraces.includes(brace)) stack.push(brace);
else {
var leftBrace=stack.pop();
if(leftBrace==undefined) ok=false;
else if(leftBraces.indexOf(leftBrace)!=rightBraces.indexOf(brace)) ok=false;
}
}
if(stack.length) ok=false;
return ok;
}
Code assumes only braces (no spaces or other characters).
I'm using string.indexOf() that matches for leftBraces and rightBraces.
Also, within the for loop, notice the termination part (2nd): i<braces.length && ok - doesn't "have to" use the iterator and, if I'm not mistaken, can even be empty...
var validBraces = (s) => {
let objO = {'(': 0, '[': 1, '{': 2};
let objC = {')': 0, ']': 1, '}': 2};
let stack = [];
for (let i=0; i<s.length; i++) {
if (objO.hasOwnProperty(s[i])) {
if (stack.length === 0 || stack[stack.length-1].idx!==objO[s[i]])
stack.push({idx: objO[s[i]], count: 1});
else
stack[stack.length-1].count++;
}
else if (objC.hasOwnProperty(s[i])) {
if (stack.length === 0 || stack[stack.length-1].idx!==objC[s[i]])
return false;
else {
stack[stack.length-1].count--;
if (stack[stack.length-1].count===0)
stack.pop();
}
}
}
return stack.length === 0;
};
console.log(validBraces("(){}[]"));
console.log(validBraces("([{}])"));
console.log(validBraces("(})"));
console.log(validBraces("[(])"));
console.log(validBraces("[({})](]"));
Here is a simplified solution:
let isMatchingBraces = function(str) {
let stack = [];
let symbol = {
'(': ')',
'[': ']',
'{': '}'
};
for (let i = 0; i < str.length; i += 1) {
// If character is an opening brace add it to a stack
if (str[i] === '(' || str[i] === '{' || str[i] === '[') {
stack.push(str[i]);
}
// If that character is a closing brace, pop from the stack, which will also reduce the length of the stack each time a closing bracket is encountered.
else {
let last = stack.pop();
//If the popped element from the stack, which is the last opening brace doesn’t match the corresponding closing brace in the symbol, then return false
if (str[i] !== symbol[last]) {
return false
};
}
}
// After checking all the brackets of the str, at the end, the stack is not
// empty then fail
if (stack.length !== 0) {
return false
};
return true;
}
function validBraces(braces){
let par =0;
let bra =0;
let cur =0;
for(let i =0; i<braces.length; i++){
if(braces[i]==="("){
par++;
}
if(braces[i]===")"){
par--;
}
if(braces[i]==="["){
bra++;
}
if(braces[i]==="]"){
bra--;
}
if(braces[i]==="{"){
cur++;
}
if(braces[i]==="}"){
cur--;
}
}
if(par<0 || bra<0 || cur<0){
return false;
}
return true;
};
Here is my solution:
var isValid = function (s) {
let charMap = new Map();
for (let i = 0; i < s.length; i++) {
charMap.set(s[i], i);
}
return Boolean(
charMap.get("(") < charMap.get(")") &&
charMap.get("(") % 2 != charMap.get(")") % 2 &&
charMap.get("{") < charMap.get("}") &&
charMap.get("{") % 2 != charMap.get("}") % 2 &&
charMap.get("[") < charMap.get("]") &&
charMap.get("[") % 2 != charMap.get("]") % 2
);
};
Explanation:
In order to achieve a quick and short solution, I have identified the common pattern of validity for opening/closing braces.
The common pattern for opening and closing braces' validity is that if say the opening(closing) stands at the even index in the string, the other one should be odd and vice versa. Example {}, {[]}, {()[]}, {[()]}.
Because we want to avoid a double loop for performance reasons, we are using a Hash Table via Map() to store the character and the index.
An alternative for getting the character's index would be using Array's find or another method, but that would end up in a second loop over the values which we want to avoid.
Finally, once the indexes of and the characters are stored in the charMap, we check whether or not the stored closing/opening characters' standing (odd/even) in the string is not equal, e.g. if '(' is odd the ')' should be even and vice versa.
We check this via the remainder (%) operator, i.e. a number's remainder of 2 is 0 if even.
Additionally, we need to check whether the order of braces is correct, e.g. if '(' is before '}';
The Boolean() function coerces the comparisons in the desired result.

Does the input string have a . or ? or ' or space?

Im writing a program that will tell you if the input string contains a period, question mark, colon or space. If it doesn't it'll return "false". If it does, it'll return all of the characters before the found punctuation. Ex. str= "grey cat", program will return "grey" because it was stopped by the space. Can I use "or" in Javascript? EDIT Im trying to do this without any built-in functions. Im not looking for an efficient way
update - now it's just printing the str. How do I get it to just print what comes before the punctuation (if any)
function find_punctuation(str){
let result = "";
for (let i = 0; i < str.length; i ++ )
if (str[i] === "." || str[i] === "?"|| str[i] === "" || str[i] === ","){
}
else result += str[i]
return result
}
console.log(find_punctuation('he. y'));
function find_punctuation(str) {
let result = "";
for (let i = 0; i < str.length; i++) {
// Determine if the current character is punctuation.
const is_punctuation = (
str[i] === "." ||
str[i] === "?" ||
str[i] === " " ||
str[i] === ","
);
if (is_punctuation) {
// If the current character is punctuation, then exit the loop.
break;
} else {
// Otherwise, keep adding to the result string.
result += str[i];
}
}
// The result string will now contain all characters until the first
// punctuation character, because the loop that added characters to
// this string was exited as soon as the first punctuation character
// was detected.
return result;
}
console.log(find_punctuation('he. y'));
console.log(find_punctuation('hell,o'));
console.log(find_punctuation('hello'));
console.log(find_punctuation('cat?erpillar'));
console.log(find_punctuation('grey cat'));
Use a regular expression:
function find_punctuation(str) {
let result = str.match(/^(.*?)[.?: ]/);
if (result) {
return result[1];
} else {
return false;
}
}
console.log(find_punctuation('he.y'));
console.log(find_punctuation('hey'));
Try this:
function find_punctuation(str){
let result = "";
for (let i = 0; i < str.length; i ++ )
if (str[i] === "." || str[i] === "?" || str[i] === " ") break
else result += str[i]
return result
}
console.log(find_punctuation('he.y'));

Checking if a letter in a String is Upper Case

I am trying to complete the Caesar Cipher in JavaScript. I need a peice of code that checks to see if a letter in a string is upper case or lower case.
const caesar = function(str) {
for (i = 0; i < str.length; i++) {
if (str[i] === str[i].toUpperCase) {
console.log('YES');
} else {
console.log('NO');
}
}
}
caesar("HeLLO")
Where am I going wrong?
UPDATE: Additional Question
Here is my full code - I swapped out my check for str[i] = str[i].toUpperCase() TO 64 < asciiNum < 91 but the check doesn't work.
Any idea why using ASCII numbers to check for capital is not working in this instance?
const caesar = function(str, shift) {
var solved = "";
for (i=0; i < str.length; i++){
var asciiNum = str[i].charCodeAt();
console.log(asciiNum);
if (64 < asciiNum < 91) { // check for upper cased
newNum = asciiNum + shift;
if(newNum > 90){
solved += String.fromCharCode(newNum - 26);
} else {
solved += String.fromCharCode(newNum);
}
} else if (96 < asciiNum < 123) { //check for lower case
newNum = asciiNum + shift;
if(newNum > 122){
solved += String.fromCharCode(newNum - 26);
} else {
solved += String.fromCharCode(newNum);
}
}
}
console.log(solved);
}
caesar("Hello, World!", 5);
Your issue was you weren't calling toUpperCase(). The computer saw it but didn't know it was supposed to run the function. To fix it, just put parentheses.
However, to make it cleaner, I'd restructure this like so:
// Gets a string from the user to test
// Replace this with whatever string should be tested (probably a variable)
var str = prompt("What string should be tested?");
const caesar = function(arg) {
return arg.split("").every(function(e) {
/* Makes an array of characters and tests to see
if every character satisfies the conditions */
if (e === e.toUpperCase()) { // If the character is upper case
return true; // Return true; the program should test the next character
} else {
console.log(`${e} was not uppercase`);
return false;
// Return false
// The program should stop, because it detected a lowercase character
}
});
}
console.log(`The result of running caesar() on string '${str}' was ${caesar(str)}`);
/* Instead of using console.log inside the function
Return the *result* of the function so that you can use it later */
This method is faster to run and a little cleaner.
If you want to check if every letter is uppercase, leave it as it is. If you want to check if some letters are uppercase, change the every to some. If you want to reverse and check if all characters (or some) are lowercase, replace the e === e.toUpperCase() with e === e.toLowerCase() or e !== e.toUpperCase(). If a letter is not uppercase, it puts which one it was in the console and stops checking others. After it's finished, it puts whether all were uppercase in the string.
Only missing part in your code is a paranthesis () in toUpperCase.
You're missing parentheses after toUpperCase.
if (str[i] === str[i].toUpperCase) {
For JS you're trying to access a toUpperCase property instead call a function.

Writing trim left in JavaScript with replace / regular expressions

I'm attempting to make a program that removes excess spaces from a string. I'm attempting to make the first two functions I expect to need. After doing some testing and consulting a classmate I can't figure out what is wrong with the second function (I'm fairly confident it's the second function)?
var isWhiteSpace = function(char) {
var out = false;
if (char === ' ' || char === '\f' || char === '\n' || char === '\r' || char === '\t') {
out = true;
}
return out;
};
var removeLeadingSpaces = function(s) {
var i;
for (i = 0; i < s.length; i++) {
if (isWhiteSpace(s.charAt(i))) {
s.replace(s.charAt(i), '');
}
}
return s;
};
s = s.replace(/^\s+/,""); would be simpler than running a loop.
This is because javascript's regular expressions already knows what whitespace is (\s) and knows how to pull from the beginning of a string (^) and can recurse on its own (+).
Use s=s.replace(s.charAt(i), '');
The replace method doesn't modify the original string - it returns a value.

Categories