You don’t need regex for that. A simpler way is to count the parentheses. You iterate by the string characters, and if you find a (, increments the counter, and if you find a ), decrease.
There is only one catch: if the string starts with ) for example, you cannot decrease, otherwise the counter will be negative. In this case you have to consider that the ( corresponding, then should account for 1 more for that case.
To another answer said to simply count the amount of ( and ) and subtract from each other, but what if the string is )(? In this case, if we count only and subtract, it will give zero. But I understand that in this case 2 parentheses are missing (one before the ) and another after the (), then it would have to be so:
function quantosParentesesFaltam(str) {
var naoAbertos = 0, qtd = 0;
for (var c of str) {
if (c == '(') { // abriu um parênteses
qtd++;
} else if (c == ')') {
if (qtd == 0) {
// encontrei um ) sem o ( correspondente
naoAbertos++;
} else {
// fechou o parênteses, diminui o contador pois está ok
qtd--;
}
}
}
return qtd + naoAbertos;
}
console.log(quantosParentesesFaltam('(()()')); // 1
console.log(quantosParentesesFaltam('(((')); // 3
console.log(quantosParentesesFaltam('())()')); // 1
console.log(quantosParentesesFaltam(')(')); // 2
console.log(quantosParentesesFaltam(')))(')); // 4
console.log(quantosParentesesFaltam('(()())')); // 0
Now if the idea is to tell and fix the string, just adapt the above case to add the missing parentheses in the string:
function conserta(str) {
var balanceada = str;
var naoAbertos = 0, qtd = 0;
for (var c of str) {
if (c == '(') { // abriu um parênteses
qtd++;
} else if (c == ')') {
if (qtd == 0) {
// encontrei um ) sem o ( correspondente
naoAbertos++;
// adiciona o ( no início
balanceada = '(' + balanceada;
} else {
// fechou o parênteses, diminui o contador pois está ok
qtd--;
}
}
}
// adiciona os ) que faltam
for(var i = 0; i < qtd; i++) {
balanceada += ')';
}
return `${qtd + naoAbertos} - "${balanceada}"`;
}
console.log(conserta('(()()')); // 1 - "(()())"
console.log(conserta('(((')); // 3 - "((()))"
console.log(conserta('())()')); // 1 - "(())()"
console.log(conserta(')(')); // 2 - "()()"
console.log(conserta(')))(')); // 4 - "((()))()"
console.log(conserta('(()())')); // 0 - "(()())"
Basically, if I found a ) without the ( corresponding (which is when the current character is ) and the accountant qtd is zero), I know I have to add one ( at first.
Then at the end of the first for, the accountant qtd will have the amount of ( which have not been closed, so just add that same amount of ) in the end.
You can even use regex
Although I find the above solutions much simpler, you can use regex.
Assuming the string has only characters ( and ) (there is no no other different character from these), one idea is to look for pairs of () (namely, a ( followed immediately by a )) and go removing them from the string, until no one.
What is left in the string are the unbalanced ones. So if you have any ) at the beginning, it is because missing add ( at first, and if you have ( at the end, just add ) in the end.
Thus:
function consertaComRegex(str) {
var r = /\(\)/g;
var s = str, tmp;
// enquanto tiver () para ser removido, continua
while ((tmp = s.replace(r, '')) != s) {
s = tmp;
}
if (s.length == 0) {
return `0 - "${str}"`;
}
// verifica se começa com um ou mais )
var match = s.match(/^\)+/);
if (match) { // adiciona os ( que faltam no início
for(var i = 0; i < match[0].length; i++) str = '(' + str;
}
// verifica se termina com um ou mais (
var match = s.match(/\(+$/);
if (match) { // adiciona os ) que faltam no final
for(var i = 0; i < match[0].length; i++) str += ')';
}
return `${s.length} - "${str}"`;
}
console.log(consertaComRegex('(()()')); // 1 - "(()())"
console.log(consertaComRegex('(((')); // 3 - "((()))"
console.log(consertaComRegex('())()')); // 1 - "(())()"
console.log(consertaComRegex(')(')); // 2 - "()()"
console.log(consertaComRegex(')))(')); // 4 - "((()))()"
console.log(consertaComRegex('(()())')); // 0 - "(()())"
Friend, sorry for the ignorance. Looking at your code I understood the increment and decrement part. but I don’t understand how he knows in which position he should add parentheses, could you please explain to me?
– DeElfos
@Deelfos I added an explanation to the answer
– hkotsubo
thank you very much! Now I understand!
– DeElfos