I have written the following code to check if some input to the function contains balanced brackets:
def balanced_brackets(text):
brackets = [ ('(',')'), ('[',']'), ('{','}'),('<','>')]
s = 0
e = 1
st = Stack()
for i in text:
for pair in brackets:
if i == pair[s]:
st.push(i)
elif i == pair[e] and not st.isEmpty() and st.pop() != pair[s]:
return False
if st.isEmpty():
return True
else:
return False
This code is working for input such as '()(())()' but it failed when I tried it for 'zn()((b)())q())()l()d(r)'. Can anyone help me identify what the problem is? Thanks.
Your problem is with the and not st.isEmpty()==0. When it gets to the unbalanced ')', all the previous ones have balanced out, so st is empty.
If you have a i == pair[e], and your stack is empty, you want to return False.
You also want to return False if you pop and it isn't pair[e]. But you don't want to pop if the stack is empty.
What you have now, in condition 1, just keeps going. You need to change around the condition there so that it accounts for both, or have two elifs. The former can be achieved with some nesting ands and ors.
By the way; unless you want to do something fancy with it, there's no real need to implement a stack. You can just use a list instead, with l.pop, len(l), and l.append.
This works.It needs a stack module to import. It will keep track of matched pairs.
def multi_bracket_validation(input):
""" test for matching brackets and return bool """
if type(input) is str:
open_b = '({]'
closed_b = ')}]'
compare = Stack()
for brac in input:
if brac in open_b:
compare.push(brac)
elif brac in closed_b:
if compare.top is None:
return False
if closed_b.index(brac) != open_b.index(compare.pop().val):
return False
return compare.top is None
return False
Related
While the provided code I created works, it is non-scalable and slow. I need a way to determine if a token (t) is the same as any element in several arrays. However, it cannot match more than one array, as one list might supersede the other. Is there any way to succinctly and quickly program this in python other than using tons of individual functions?
def keyword(t):
for n in keywords:
if t == n:
return True
break
else:
return False
def separator(t):
for n in separators:
if t == n:
return True
break
else:
return False
def operator(t):
for n in operators:
if t == n:
return True
break
else:
return False
def identifier(t):
if keyword(t) is False and operator(t) is False and separator(t) is False:
return True
else:
return False
The keyword function is just n in keywords - a test of containment. This is generally faster using a set. So, combine call of your categories and test from there.
identifiers = {(*keywords, *separators, *operators)}
def identifier(t):
return t in identifiers
the way I find that you could do what you ask is simply using a function that requires 2 parameters and creating an array that contains all the arrays you need to compare, making a function that cycles through each of the arrays trying to find a match.
I do it this way:
keywords = ["Hi", "World"]
separators = ["Hola", "Mundo"]
operators = ["My", "name"]
lists = [keywords, separators, operators]
t = "F"
def comparator(token, arrays):
for array in arrays:
for item in array:
if token == item:
return False
else:
return True
print(comparator(token=t, arrays=lists))
I'm not getting any error or any results so I can't quite pinpoint the issues.
It's based on the 'stack' data structure.
def is_match(p1, p2):
return (p1,p2) in ['(,)', '{,}', '[,]']
def is_open(param):
return param in '([{'
def is_balanced(exp):
stack = []
for i in range(len(exp)):
if is_open(exp[i]):
stack.append(exp[i])
else:
top = stack.pop()
if not is_match(top,str(exp[i])):
return False
if stack == []:
return True
else:
return False
is_balanced('{[}')
First of all, you are not printing anything. Your function always returns False, but without a print, the result is discarded.
Secondly, you have logic errors. The most obvious one is ('(', ')') is never equal to '(,)'. And if you don't test if the stack is empty as you pop, so in case of input such as '}', you will get an error. And str(exp[i]) is redundant, exp[i] is a string already. Finally,
if condition:
return True
else:
return False
is an antipattern; you can simply say return condition (or, if it is not a boolean and you want it to be, return bool(condition); not needed in this case, as the result of equality comparison is always a boolean).
The problem is formulated as follows:
Write a recursive function that, given a string, checks if the string
is formed by two halves equal to each other (i.e. s = s1 + s2, with s1
= s2), imposing the constraint that the equality operator == can only be applied to strings of length ≤1. If the length of the string is
odd, return an error.
I wrote this code in Python 2.7 that is correct (it gives me the right answer every time) but does not enter that recursive loop at all. So can I omit that call here?
def recursiveHalfString(s):
##param s: string
##return bool
if (len(s))%2==0: #verify if the rest of the division by 2 = 0 (even number)
if len(s)<=1: # case in which I can use the == operator
if s[0]==s[1]:
return True
else:
return False
if len(s)>1:
if s[0:len(s)/2] != s[len(s)/2:len(s)]: # here I used != instead of ==
if s!=0:
return False
else:
return recursiveHalfString(s[0:(len(s)/2)-1]+s[(len(s)/2)+1:len(s)]) # broken call
return True
else:
return "Error: odd string"
The expected results are True if the string is like "abbaabba"
or False when it's like anything else not similat to the pattern ("wordword")
This is a much simplified recursive version that actually uses the single char comparison to reduce the problem size:
def rhs(s):
half, rest = divmod(len(s), 2)
if rest: # odd length
raise ValueError # return 'error'
if half == 0: # simplest base case: empty string
return True
return s[0] == s[half] and rhs(s[1:half] + s[half+1:])
It has to be said though that, algorithmically, this problem does not lend itself well to a recursive approach, given the constraints.
Here is another recursive solution. A good rule of thumb when taking a recursive approach is to first think about your base case.
def recursiveHalfString(s):
# base case, if string is empty
if s == '':
return True
if (len(s))%2==0:
if s[0] != s[(len(s)/2)]:
return False
else:
left = s[1:len(s)/2] # the left half of the string without first char
right = s[(len(s)/2)+1: len(s)] # the right half without first char
return recursiveHalfString(left + right)
else:
return "Error: odd string"
print(recursiveHalfString('abbaabba')) # True
print(recursiveHalfString('fail')) # False
print(recursiveHalfString('oddstring')) # Error: odd string
This function will split the string into two halves, compare the first characters and recursively call itself with the two halves concatenated together without the leading characters.
However like stated in another answer, recursion is not necessarily an efficient solution in this case. This approach creates a lot of new strings and is in no way an optimal way to do this. It is for demonstration purposes only.
Another recursive solution that doesn't involve creating a bunch of new strings might look like:
def recursiveHalfString(s, offset=0):
half, odd = divmod(len(s), 2)
assert(not odd)
if not s or offset > half:
return True
if s[offset] != s[half + offset]:
return False
return recursiveHalfString(s, offset + 1)
However, as #schwobaseggl suggested, a recursive approach here is a bit clunkier than a simple iterative approach:
def recursiveHalfString(s, offset=0):
half, odd = divmod(len(s), 2)
assert(not odd)
for offset in range(half):
if s[offset] != s[half + offset]:
return False
return True
so I'm new to programming (and python) and I have to make this program that returns True if the string has zero or one dot characters ("." characters) and return False if the string contains two or more dots
here is what I currently have, I cannot get it to work for me, please correct me if I am wrong, thanks!
def check_dots(text):
text = []
for char in text:
if '.' < 2 in text:
return True
else:
return False
Use the builtin Python function list.count()
if text.count('.') < 2:
return True
It can be even shorter if instead of an if-else statement, you do
return text.count('.') < 2
Also, there are some errors in your function. All you need to do is
def check_dots(text):
return text.count('.') < 2
A correct and shorter version would be:
return text.count('.') <= 1
Python has a function called count()
You can do the following.
if text.count('.') < 2: #it checks for the number of '.' occuring in your string
return True
else:
return False
A shortcut would be:
return text.count('.')<2
Let's analyze the above statement.
in this part, text.count('.')<2: It basically says "I will check for periods that occur less than twice in the string and return True or False depending on the number of occurences." So if text.count('.') was 3, then that would be 3<2 which would become False.
another example. Say you want it to return False if a string is longer than 7 characters.
x = input("Enter a string.")
return len(x)>7
The code snippet len(x)>7 means that the program checks for the length of x. Let's pretend the string length is 9. In this case, len(x) would evaluate to 9, then it would evaluate to 9>7, which is True.
I shall now analyze your code.
def check_dots(text):
text = [] ################ Don't do this. This makes it a list,
# and the thing that you are trying to
# do involves strings, not lists. Remove it.
for char in text: #not needed, delete
if '.' < 2 in text: #I see your thinking, but you can use the count()
#to do this. so -> if text.count('.')<2: <- That
# will do the same thing as you attempted.
return True
else:
return False
I am trying to write a function which is supposed to compare list structures (the values are indifferent). The problem is that I have two lists which are unequal but the function still returns True even though it actually goes into the else part. I don't understand why and what I did wrong. Here is my code:
def islist(p): #is p a list
return type(p)==type(list())
def ListeIsomorf(a,b):
if len(a)==len(b):
for i,j in zip(a,b):
if islist(i) and islist(j):
ListeIsomorf(i,j)
elif islist(i) or islist(j):
return(False)
return(True)
else:
print(a,"length from the list isn't equal",b)
return(False)
#example lists
ListeE = [[],[],[[]]]
ListeD = [[],[],[[]]]
ListeF = [[[],[],[[]]]]
ListeG = [[],[[]],[[]]]
ListeH = [1,[3]]
ListeI = [1,3]
#tests
print(ListeIsomorf(ListeD,ListeE)) # True
print(ListeIsomorf(ListeD,ListeF)) # False
print(ListeIsomorf(ListeD,ListeG)) # False
print(ListeIsomorf(ListeH,ListeI)) # False
So the problem only occurs with the third print(ListeIsomorf(ListeD,ListeG)) # False. It actually goes into the else part and does print the "length from the list isn't equal" but it doesn't stop and it doesn't give out the return(False). Am I missing something?
The problem is that when your function calls itself recursively:
ListeIsomorf(i,j)
it ignores the returned value.
Thus the comparisons that take place at the second level of recursion have no effect on what the top level returns.
Changing the above to:
if not ListeIsomorf(i,j):
return(False)
fixes the problem.