'Valid Braces - CodeWars Challenge

There is a challenge on codewars that asks you to check whether a string of parentheses, brackets, and curly braces is valid.

A string of braces is considered valid if all braces are matched with the correct brace.

I.e. "()" is valid and "[(])" is not.

"(){}[]" is valid and "[({})](]" is not. Etc.

I've been able to create some logic to check for whether or not there are the right number of opening and closing braces.

ATTEMPT:

function validBraces(braces) {

  let parenCount = 0;
  let squareBracketCount = 0;
  let curlyBraceCount = 0;

    for (let i =0; i < braces.length; i++) {
      let character = braces[i];
        if (character === "(") {
          parenCount -= 1;
          }
        if (character === ")") {
          parenCount += 1;
          }
        if (character === "[") {
          squareBracketCount -= 1;
          }
        if (character === "]") {
          squareBracketCount += 1;
        }
        if (character === "{") {
          curlyBraceCount -= 1;
        }
        if (character === "}") {
          curlyBraceCount += 1;
        }
      }
      if (parenCount === 0 && squareBracketCount === 0 && curlyBraceCount === 0) {
        return true;
      } 
      else {
        return false;
      }
}

But I've not been able to come up with a way to check for whether or not the opening brace "closes" before the next type of brace opens.

Maybe something like this?

if (
  (firstChar === "(" && lastChar === ")") ||
  (firstChar === "{" && lastChar === "}") ||
  (firstChar === "[" && lastChar === "]")
) {
  return true;
} else {
  return false;
}

But then this would have to be checked in accordance with my other if-statement...(?)

EDIT: Key to understanding this challenge is that the closing brace must either come directly after the opening brace or it must be "parallel" - in symmetry with the other.



Solution 1:[1]

You can use array to keep track of previously appeared opening braces and once any closing tag appears you need to match it with the last value of array if it's matching pop the last value out of else else return false, in the end if you're left with empty array return true else return false

function validBraces(braces){
  let tracer = []
  for(let i=0;i < braces.length; i++){
    if ( braces[i] === "(" || braces[i] === "{" || braces[i] === "["){
      tracer.push(braces[i])
    } else{
      if(tracer.length === 0) return false
      let lastValue = tracer[tracer.length-1]
      if( (braces[i] === ']' && lastValue === '[') || (braces[i] === '}' && lastValue === '{') || (braces[i] === ')' && lastValue === '('))
      {
        tracer.pop()
      } else {
        break;
      }
    }
  }
  return tracer.length === 0
}


console.log(validBraces( "()" )) // true
console.log(validBraces( "[]" )) // true
console.log(validBraces( "{}" )) // true
console.log(validBraces( "(){}[]" )) // true
console.log(validBraces( "([{}])" )) // true
console.log(validBraces( "(}" )) // false
console.log(validBraces( "[(])" )) // false
console.log(validBraces( "({})[({})]" )) // true
console.log(validBraces( "(})" )) // false
console.log(validBraces( "(({{[[]]}}))" )) //true
console.log(validBraces( "{}({})[]" )) // true
console.log(validBraces( ")(}{][" )) // false
console.log(validBraces( "())({}}{()][][" )) // false
console.log(validBraces( "(((({{" ))  // false
console.log(validBraces( "}}]]))}])" )) // false

Solution 2:[2]

You don't really need to use arrays here, you can just use regex and recursion:

const regex = /\(\)|\[\]|\{\}/;
const validBraces = braces => regex.test(braces)
  ? validBraces(braces.replace(regex, ''))
  : '' === braces

console.log(validBraces('{{}}')) // true
console.log(validBraces('{{[]}}')) // true
console.log(validBraces('{[{}]}')) // true
console.log(validBraces('({{}})')) // true
console.log(validBraces('{[()]}')) // true
console.log(validBraces('{{}[}')) // false
console.log(validBraces('{{]}}')) // false
console.log(validBraces('{}}')) // false
console.log(validBraces('{({}}')) // false
console.log(validBraces('((}}')) // false
console.log(validBraces('}[)}')) // false

Solution 3:[3]

In scala you can do this

object Kata {

  def validBraces(s: String): Boolean =
    s.replace("()", "").replace("[]", "").replace("{}", "") match { case "" => true; case `s` => false; case x => validBraces(x) }
}

Solution 4:[4]

function validBraces(braces){
 while(/\(\)|\[\]|\{\}/g.test(braces)){braces = braces.replace(/\(\)|\[\]|\{\}/g,"")}
 return !braces.length;
}

// double regex 

Solution 5:[5]

I have done it in Scala with some tests and it works. In case the string's length is 2 if dont need to enter the recursive call because in the match you have already checked if it correct or not :

   object Kata1{
        def validBraces(s: String): Boolean ={
          var valid: Boolean = true
          if(s.length > 1){
           s(0) match{
              case '('  => if( s(1) == ')' || s(s.length-1) == ')'){
                if(s.length != 2){
                  if(s(1) == ')'){
                    valid = validBraces(s.substring(2, s.length))
                  }else{
                    valid = validBraces(s.substring(1, s.length-1))
                  }
                }
          } else {
                if(s.lastIndexOf(')') != -1){
                 var newS = s.substring(0, s.indexOf(')')).concat(s.substring(s.indexOf(')')+1, s.length))
                  valid = validBraces(newS.substring(1, s.length-1))
                }else valid = false
           }
        case '['  => if( s(1) == ']' || s(s.length-1) == ']') {
         if(s.length != 2){
          if(s(1) == ']'){
           valid = validBraces(s.substring(2, s.length))
         }else{
           valid = validBraces(s.substring(1, s.length-1))
         }
       }
      } else {
       if(s.lastIndexOf(']') != -1){
         var newS = s.substring(0, s.indexOf(']')).concat(s.substring(s.indexOf(']')+1, s.length))
        valid = validBraces(newS.substring(1, s.length-1))
      }else valid = false
    }
    case '{'  => if( s(1) == '}' || s(s.length-1) == '}') {
      if(s.length != 2){
        if(s(1) == '}'){
          valid = validBraces(s.substring(2, s.length))
        }else{
          valid = validBraces(s.substring(1, s.length-1))
        }
      }
    } else {
      if(s.lastIndexOf('}') != -1){
        var newS = s.substring(0, s.indexOf('}')).concat(s.substring(s.indexOf('}')+1, s.length))
        valid = validBraces(newS.substring(1, s.length-1))
      }else valid = false
    }
    case _ => valid = false
  }
  /*if(s.length != 2 && valid){
    if(s(1) == ')'  || s(1) == '}'  || s(1) == ']' ){
      valid = validBraces(s.substring(2, s.length))
    }else{
      valid = validBraces(s.substring(1, s.length-1))
    }
  }*/
}else{
  valid = false
}

if(s.length == 0){
  valid = true
}
valid
 }
 }

 Kata1.validBraces("()") //true
 Kata1.validBraces("[()]") //true
 Kata1.validBraces("[(])") //false
 Kata1.validBraces("([{}])") //true
 Kata1.validBraces("([{]})") //false
 Kata1.validBraces("{({{()}({}())})}")//true
 Kata1.validBraces("({]}{")//false

Solution 6:[6]

My JavaScript solution of this kata is simple to understand and passes all tests. Yet im aware its optimization isn't top-notch. It simply eliminates elements step by step:

  1. Start: ( { [] } ) || ( { [] } }

  2. Then: ( {} ) || ( {} }

  3. Then: () || (} Finish: clear || leftovers

  4. When length = 0 it passes, and when length > 0 it wont

   function validBraces(braces){
while(braces.indexOf("{}") !== -1 || braces.indexOf("()") !== -1 || braces.indexOf("[]") !== -1){
    braces = braces.replace("{}", "").replace("()", "").replace("[]", "");
}
return braces.length === 0 ? true: false;

console.log(validBraces("(({{[[]]}}))"));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Mike K
Solution 3 ravi malhotra
Solution 4 General Grievance
Solution 5
Solution 6