简体   繁体   中英

Trying to balance parantheses but don't understand what's wrong with my code

I'm trying to balance parenthesis on python using Stacks. I've been trying to figure out what's wrong but I don't get it. Here's the code I wrote:

class Stack:

def __init__(self):
    self.opens = []
    self.closes = []

def empty_opens(self):
    return self.opens == []

def empty_closes(self):
    return self.closes == []

def add_opens(self, item):
    return self.opens.append(item)

def add_closes(self, item):
    return self.closes.append(item)

def is_empty_opens(self):
    return len(self.opens) == 0

def remove_opens(self):
    if not self.is_empty_opens():
        return self.opens.pop(0)

def is_empty_closes(self):
    return len(self.closes) == 0

def remove_closes(self):
    if not self.is_empty_closes():
        return self.closes.pop()


def checker(string):
open = "([{"
close = ")]}"
p = Stack()
for i in string:
    if i == "(" or i == "[" or i == "{":
        p.add_opens(i)
    elif i == ")" or i == "]" or i == "}":
        p.add_closes(i)
if len(p.opens) != len(p.closes):
    return False
else:
    for a in p.opens:
        for b in reversed(p.closes):
            if open.index(a) == close.index(b):
                p.remove_opens()
                p.remove_closes()
if len(p.opens) == 0 and len(p.closes) == 0:
    return True
else:
    return False

The code works overall but it seems that it doesn't remove the last values of the "for" loop. I added a print after the "for" loops to try and figure it out and this is what i got:

    ...
    else:
    for a in p.opens:
        for b in reversed(p.closes):
            if open.index(a) == close.index(b):
                p.remove_opens()
                p.remove_closes()
    print(p.opens)
    print(p.closes)
if len(p.opens) == 1 and len(p.closes) == 1:
   ...

Python Console:

checker("{[()]}")
['(']
[')']
False

checker("{[(]]}")
['[', '(']
[']', ']']
False

I also tried to change the code, instead of using .index() I tried to use range(len()), but it didn't work again:

    ...
    else:
    for a in range(len(p.opens)):
        for b in reversed(range(len(p.closes))):
            if a == b:
                p.remove_opens()
                p.remove_closes()
    print(p.opens)
    print(p.closes)
if len(p.opens) == 0 and len(p.closes) == 0:
   ...

  Python Console:

  checker("{[()]}")
  ['(']
  [')']
  False

  checker("{[(]]}")
  ['(']
  [']']
  False

This is probably a basic mistake but I'm slowly losing my mind over this so I ask if anyone could help.

Note on the code:

What I'm trying to do in my code is through a class create 2 lists, one for the open parenthesis: "(, [, {" and another one for the close parenthesis: "), ], }" .

The class has the simple Stack methods of adding or removing from the list.

Regarding the code itself, what I'm trying to do first is separate the characters that are parenthesis from the characters that aren't. If the code finds a parenthesis that is open, it adds to the "opens" list and if it's close, it adds to the "closes" list.

After that it checks how many items there are in each list and if they are not the same then it means right away that they are unbalanced.

Now the tricky part. If there are the same amount of parenthesis open and closed I want the code to check each one. From what I understand, for parenthesis to be balanced, the first open parenthesis in the list "opens" needs to be equal to the last closed parenthesis in the "closes" list.

Ex:

Input: { [ ( ) ] }

opens_list = [ '{', '[', '(' ]

'{' = 1 , '[' = 2 , '(' = 3

closes_list = [ ')', ']', '}' ]

')' = 1 , '[' = 2 , '{' = 3

So they have to match, Opens(1) = Closes(3), Opens(2) = Closes(2) and Opens(3) = Closes(3)

Based on this what i did was reverse the closes list so that each index has to correspond. In the beggining of the code I wrote:

def checker(string):
 open = "([{"
 close = ")]}"
 ...

So what I'm trying to do is take the first character in the opens_list, "{" , check what index it has in the "open variable" , it has the 3rd index and do the same for the closes list.

If they have the same index it removes them. In the end, if both list don't have any elements then it's balanced.

This is a bit messy, english is not my first language and I don't know all the right concepts of things in python but I hope it's understandable. I honestly just want to know what's wrong so I don't repeat the same mistake in the future. If anyone can understand this and help, I would appreciate a lot.

Checking for matching delimiters using a stack only requires 3 basic operations:

  1. If a character is an opening delimiter, add it to the stack
  2. If a character is a closing delimiter, pop the stack and see if it matches the closing character.
  3. Checking if the stack is empty when the input is exhausted.

There's no real need for a dedicated Stack class; all three operations are easily implemented using a bare list.

def checker(string):
    match = dict(["()", "{}", "[]"])  # Mapping of opening delimiter to its closing partner
    st = []  # Initially empty stack
    for c in string:
        if c in match:  # Push an opening delimiter
            st.append(c)
        elif c in match.values():
            # Try to pop the most recent opening delimiter;
            # return False if that fails or it doesn't match the closing delimiter
            if not st or match[st.pop()] != c:
                return False

    # Check if there were any unclosed delimiters
    return (not st)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM