-1

The Problem:

I am attempting to write some python code that searches through a list and returns the index of a matching bracket. For example:

array = ["(","foo",")","(","bar","(",")",")"]
f(0) => 2
f(1) => ERROR: Not a bracket.
f(2) => 0
f(3) => 7

My Feeble Attempts:

I tried looping through the list and finding the closest bracket, but then I realised it didn't work when you had loops inside loops (loopception). I have also tried adding a counter that adds one to the counter if it's a new bracket ( and takes one if it's a close bracket ), then checks to see if it equals -1, but that doesn't work.

Previous Code:

while True:
            if(count == -1):
                iterator = j+1
                break
            else:
                j += 1
                print j
                if(commands[j] == "("):
                    count += 1
                if(commands[j] == ")"):
                    count -= 1

Where iterator is the input and commands is the array

Olly Britton
  • 115
  • 7
  • 5
    You mention you have attempts. Please show that code – OneCricketeer Jan 14 '17 at 15:28
  • Your last sentence basically describes how you should approach this, so you'll need to show us what "that doesn't work" means. – glibdud Jan 14 '17 at 15:30
  • 1
    Iterating through the list from the index with a counter staring at 1 that increment for opening brackets and decrement for closing brackets should work. – Ted Klein Bergman Jan 14 '17 at 15:32
  • @OllyBritton And what exactly happens when you run that code? – glibdud Jan 14 '17 at 15:35
  • Also, how are `j` and `count` initialized? And what is the purpose of `iterator`? – glibdud Jan 14 '17 at 15:36
  • @glibdud j is set to iterator and count is set to zero. Iterator is the the index of the character I want to count from – Olly Britton Jan 14 '17 at 15:40
  • That would be useful to add to the question, along with a description of what happens when you run the code (finds wrong bracket? does nothing? raises exception? (if so, add full stack trace)) – glibdud Jan 14 '17 at 15:44
  • Does this help? http://stackoverflow.com/questions/29991917/indices-of-matching-parentheses-in-python – PM 2Ring Jan 14 '17 at 15:45

2 Answers2

2

Assuming the array holds a correct sequence of opening/closing backets:

array = ["(","foo",")","(","bar","(",")",")"]

bracketPositions = []
for i, item in enumerate(array):
    if i == 0 and item == ')':
        print("Non sense ! Exit")
        break

    if item == '(':
        bracketPositions.append(i)
    elif item ==')':
        if len(bracketPositions) > 0:
            openingPosition = bracketPositions.pop()
            print(openingPosition, '-->', i)
    else:
        print('ERROR: Not a bracket. Word is: %s.' % item)

Prints:

ERROR: Not a bracket (foo).
0 --> 2
ERROR: Not a bracket (bar).
5 --> 6
3 --> 7
Maurice Meyer
  • 17,279
  • 4
  • 30
  • 47
0

With the counter variable you were on the right track, but it's difficult to say what exactly went wrong without seeing the entire code. Basically, what you have to do is: Determine in which direction to go and what to look out for. Initialize the number of matching parens to find as 1, then iterate through the array. If you find the original parens again, increment the counter, if you find the counterpart, decrement the counter. If the counter reaches zero, return the current position.

You can try something like this:

def match(array, pos):
    try:
        step  = {"(": +1,  ")": -1} [array[pos]] # go left or right?
        other = {"(": ")", ")": "("}[array[pos]] # what to look for?
        count = 1   # number of 'other' we have to find
        cur   = pos # current position
        while True:
            cur += step  # go one step further
            if array[cur] == array[pos]: # nested parens
                count += 1
            if array[cur] == other: # found match (but maybe for nested)
                count -= 1
            if count == 0:  # found match for original parens
                return cur
    except KeyError:
        # not a ( or ) or no match found
        return None

array = ["(","foo",")","(","bar","(",")",")"]
print([match(array, i) for i, _ in enumerate(array)])
# [2, None, 0, 7, None, 6, 5, 3]
tobias_k
  • 81,265
  • 12
  • 120
  • 179