The challenge

In this challenge, you will be given a string with brackets and an index of an opening bracket and your task will be to return the index of the matching closing bracket. Both the input and returned index are 0-based. An opening brace will always have a closing brace. Return an error if there is no answer.

Examples:

solve("((1)23(45))(aB)", 0) = 10 // the opening brace at index 0 matches the closing brace at index 10
solve("((1)23(45))(aB)", 1) = 3 
solve("((1)23(45))(aB)", 2) = -1 // there is no opening bracket at index 2, so return -1
solve("((1)23(45))(aB)", 6) = 9
solve("((1)23(45))(aB)", 11) = 14
solve("((>)|?(*'))(yZ)", 11) = 14

Input will consist of letters, numbers, and special characters, but no spaces. The only brackets will be ( and ).

The solution in Golang

Option 1:

package solution;
import ("errors")
func Solution(s string, i uint) (uint, error) {
  if s[i] == '(' { 
    d := 0;
    for j := i+1; j < uint(len(s)); j++ {
      c := s[j];
      switch {
        case d==0 && c==')': return j, nil;
        case c=='(': d++;
        case d>0 && c==')': d--;
      }
    }
  }
  return 0, errors.New("");
}

Option 2:

package solution

import "errors"

func Solution(s string, i uint) (uint, error) {
  if string(s[i])!="(" {return 0, errors.New("Not an opening bracket")}
  o := 1
  for k := i+1 ; k < uint(len(s)) ; k++ {
    c := string(s[k])
    if c==")" {
      o--
      if o==0 {return k, nil}
    } else if c=="(" {o++}
  }
  return 0, errors.New("Not an opening bracket")
}

Option 3:

package solution

import "errors"

func Solution(str string, idx uint) (uint, error) {
  if str[idx] != '(' {
    return 0, errors.New("Not an opening bracket")
  }
  
  var stack []uint
  for i, val := range str {
      switch val {
      case '(': 
        stack = append(stack, uint(i))    // stack push

      case ')':
        n := len(stack)-1
        pop := stack[n]     // stack pop
        stack = stack[:n]
        if pop == idx {
            return uint(i), nil
        }
      }
  }
  
  return 0, errors.New("No solution")  
}

Test cases to validate our solution

package solution_test
import (
  . "github.com/onsi/ginkgo"
  . "github.com/onsi/gomega"
)
var _ = Describe("Sample tests for Solution", func() {
   It("should test that Solution returns the correct value", func() {
     Expect(Solution("((1)23(45))(aB)", 0)).To(Equal(uint(10)))
     Expect(Solution("((1)23(45))(aB)", 1)).To(Equal(uint(3)))
     _, err := Solution("((1)23(45))(aB)", 2)
     Expect(err).To(HaveOccurred())
     Expect(Solution("((1)23(45))(aB)", 6)).To(Equal(uint(9)))
     Expect(Solution("((1)23(45))(aB)", 11)).To(Equal(uint(14)))
     Expect(Solution("(g(At)IO(f)(tM(qk)YF(n)Nr(E)))", 11)).To(Equal(uint(28)))
     Expect(Solution("(g(At)IO(f)(tM(qk)YF(n)Nr(E)))", 0)).To(Equal(uint(29)))
     Expect(Solution("(>_(va)`?(h)C(as)(x(hD)P|(fg)))", 19)).To(Equal(uint(22)))
   })
})