Turning iteration into recursion - python

I want to check if the string user entered has a balanced amount of ( and )'s
ex. ()( is not balanced
(()) is balanced
def check(string):
counter=0
string=string.replace(" ","")
if string[0] is "(":
for x in string:
if x is "(":
counter=counter+1
elif x is ")":
counter=counter-1
if counter1 is 0:
print("Balanced")
else:
print("Unbalanced")
else:
print ("Unbalanced")
so this works, but how do I solve this problem with recursion? I am trying to think how I can make a variable decrease each time i call it recursively and once it's 0, stop.s

>>> def check(mystr, barometer=0):
... if not mystr:
... return barometer
... elif mystr[0] == "(":
... return check(mystr[1:], barometer+1)
... elif mystr[0] == ")":
... return check(mystr[1:], barometer-1)
... else:
... return check(mystr[1:], barometer)
...
>>> for s in ["()", "(()", "(())", "()()"]: print(s, check(s))
...
() 0
(() 1
(()) 0
()() 0
0 means you're properly balanced. Anything else means you're not balanced

A direct, equivalent conversion of the algorithm would look like this:
def check(string, counter=0):
if not string:
return "Balanced" if counter == 0 else "Unbalanced"
elif counter < 0:
return "Unbalanced"
elif string[0] == "(":
return check(string[1:], counter+1)
elif string[0] == ")":
return check(string[1:], counter-1)
else:
return check(string[1:], counter)
Use it like this:
check("(())")
=> "Balanced"
check(")(")
=> "Unbalanced"
Notice that the above algorithm takes into account cases where the closing parenthesis appears before the corresponding opening parenthesis, thanks to the elif counter < 0 condition - hence fixing a problem that was present in the original code.

Related

How to check if the parentheses and brackets are balanced?

I need to write a function that given a string with parenthesis and/or square brackets it is able to evaluate if they appear in the correct order. For example, in this string '([b])(aa)' you can see that every time a parenthesis or square bracket is open, it is closed in the correct position. However, a string like '[(a])' it is not closing the parenthesis or square brackets in the correct order as it should be '[(a)]'.
The function should return True or False depending on this correct position of both elements. I have tried the following code, but this logic seems to be infinite and it is not working if I have more than two parenthesis or square brackets opened.
def parenthesis(string):
for a in range(len(string)):
if string[a] == "(":
for b in range(a,len(string)):
if string[b] == "[":
for c in range(b,len(string)):
if string[c] == "]":
for d in range(c,len(string)):
if string[d] == ")":
return True
elif string[b] == ")":
return True
else:
return False
If I run the function over the string "([b])(aa)" it is returning false as output.
parenthesis("([b])(aa)")
How can I rewrite this function so it evaluates all the parenthesis and square brackets combinations properly?
If a right parenthesis is open before a left, you got -1 and return False
def is_balanced(string):
cnt = 0
for char in string:
if char == '(': cnt += 1
if char == ')': cnt -= 1
if cnt < 0: return False
return True if cnt == 0 else False
This is one of the stack implementations I know:
def is_balanced(s):
stack = []
for char in s:
if char == "(" or char == "{" or char == "[":
stack.append(char)
elif len(stack) <= 0:
return False
elif char == ")" and stack.pop() != "(":
return False
elif char == "]" and stack.pop() != "[":
return False
elif char == "}" and stack.pop() != "{":
return False
if len(stack) == 0:
return True
return False
This version is more DRY than the prior answer:
def is_balanced(parens: str) -> bool:
# Link: https://stackoverflow.com/a/73341167/
parens_map ={'(':')','{':'}','[':']'}
stack = []
for paren in parens:
if paren in parens_map: # is open
stack.append(paren)
elif paren in parens_map.values(): # is close
if (not stack) or (paren != parens_map[stack.pop()]):
return False
return not stack

If the round brackets is correct and full in the entire string,

I asked to write function that get string and return True if the round brackets is correct and full in the entire string.
for example: string: (()) return True, but for the string (()( return False.
I started to write but I don't know how to check the second example.
Thank you.
def function(A):
left=0
right=0
for i in range(len(A)):
if A[i]== '(':
left+=1
if A[i]== ')':
right+=1
return left==right
You have pretty much done the job in your function.
However, if you want to be aware which of them is more common on your string, you can handle with else
def some_func(A):
left=0
right=0
for i in range(len(A)):
if A[i]== '(':
left+=1
if A[i]== ')':
right+=1
if left == right:
return left == right # Obviously will return true
else:
return {'left': left, 'right' : right}
foo = some_func('((()')
print(foo)
OUTPUT:
{'left': 3, 'right': 1}
def function(A):
left=0
right=0
for i in range(len(A)):
if A[i]== '(':
left+=1
if A[i]== ')':
right+=1
if left<right:
return False
return True
Just take a counter, and if the counter never goes under 0 and the final value is 0, then this is True, otherwise this is False.
def correct_braces(string):
counter = 0
for s in string:
if s == '(':
counter += 1
if s == ')':
counter -= 1
if counter < 0: # ')(' will fall in this case
return False
return counter == 0

How do I split this into a separate if statement?

I'm trying to split the following code into a separate if statement.
def second_half(s):
return s[len(s)//2 if len(s)%2 == 0 else ((len(s)//2)+1):]
I've already tried doing the following:
def second_half(s):
if len(s) % 2 == 0:
return s[len(s)//2]
else:
return s[((len(s)//2)+1):]
and receive the following output in my doctest (although majority of my other tests passed):
Failed example:
second_half("abcdef")
Expected:
'def'
Got:
'd'
Would appreciate any help. Cheers.
In your original list-comprehension code, the start index of the slice is calculated and the last index is taken as (len(s)
But when you translate this into two if-statements, You forgot the slice operator : in the the first if condition, which caused only one element to be returned, but what you want is the whole slice in both if conditions, which will happen when you do return s[len(s)//2:] instead of return s[len(s)//2] in the first if condition
So the updated code will be
def second_half(s):
if len(s) % 2 == 0:
#Added the missing slice
return s[len(s)//2:]
else:
return s[((len(s)//2)+1):]
And the code will work as expected
print(second_half('abcde'))
#de
print(second_half('abcdef'))
#def
As commented, your first return is missing the colon.
This is called list slicing, see here for more info.
def second_half_original(s):
return s[len(s)//2 if len(s)%2 == 0 else ((len(s)//2)+1):]
def second_half_split(s):
if len(s) % 2 == 0:
return s[len(s) // 2:]
else:
return s[len(s)//2 + 1:]
Result:
>>> def second_half_original(s):
... return s[len(s)//2 if len(s)%2 == 0 else ((len(s)//2)+1):]
...
>>> def second_half_split(s):
... if len(s) % 2 == 0:
... return s[len(s) // 2:]
... else:
... return s[len(s)//2 + 1:]
...
>>> s = 'abcdef'
>>> print('Old\t{old}\nNew\t{new}'.format(
... old=second_half_original(s),
... new=second_half_split(s)
... )
... )
Old def
New def
whats happening here:
len(s)//2 if len(s)%2 == 0 else ((len(s)//2)+1)
Ternary operator expression:
syntax:
value_when_true if condition else value_when_false
this part of code will return integer (some_integer)
and then you will have:
s[some_integer:] # a[start:] items start through the rest of the array
Slicing strings:
Syntax:
substring = original_string[first_pos:last_pos]
def second_half(s):
if len(s) % 2 == 0:
n=len(s) // 2
else:
n=(len(s)//2)+1
return s[n:]
print (second_half("abcdef"))
def second_half(s):
if len(s) % 2 == 0:
return s[len(s)//2:]
else:
return s[len(s)//2)+1]
output:
def

Check whether a string is a valid number

I need to check if a string is a valid number or not.
Here are some examples of valid:
1234
-1234
12.4
0.6
-0.6
-1234567890.123456789
Non-valid:
+123
123.
.6
00.6
12-.6335
If the first digit is a 0, a decimal point "." must come after it.
I have tried the following code but it says "time limit exceeded". I'm not sure what that means.
def valid_float(number_string):
counter = 0
if number_string[0].isdigit() or number_string[0] == "-" or number_string[0] == "0":
while number_string[0] == "-":
if number_string[1].isdigit():
counter += 1
else:
counter = 0
while number_string[0].isdigit():
if number_string[1] == "." and number_string[2].isdigit():
counter += 1
else:
counter = 0
while number_string[0] == "0":
if number_string[1] == ".":
counter += 1
else:
counter = 0
if counter == 3:
return True
else:
return False
else:
counter = 0
The error you get means that the program keeps going for a long time because it is 'stuck' somewhere. Most of the time its because of a bad recursion function or, in this case, a while loop that will loop forever.
Your while loops will loop forever because you don't change the thing it checks as condition: if the condition is true in the beginning it will be true all the time so the program will never quit the while loop.
I wanted to correct your code but I can't figure out what you where trying so here is some code that will hopefully help you out:
for i in range(0,len(number_string)):
if i == 0 and number_string[0] == "." :
return false
if i != 0 and number_string[0] == "." :
continue
if i == 0 and number_string[0] == "-" :
continue
if i == 0 and number_string[0] == "0" and len(number_string[0])>1:
if number_string[1] != "." :
return false
if number_string[i].isdigit():
continue
return false

returning 1 instead of true in python

I am trying to return one instead of true in python.
The code i am working on is:
delimiters = ( '()', '[]', '{}', "''", '""' )
esc = '\\'
def is_balanced(s, delimiters=delimiters, esc=esc):
stack = []
opening = tuple(str[0] for str in delimiters)
closing = tuple(str[1] for str in delimiters)
for i, c in enumerate(s):
if len(stack) and stack[-1] == -1:
stack.pop()
elif c in esc:
stack.append(-1)
elif c in opening and (not len(stack) or opening[stack[-1]] != closing[stack[-1]]):
stack.append(opening.index(c))
elif c in closing:
if len(stack) == 0 or closing.index(c) != stack[-1]:
return False
stack.pop()
return len(stack) == 0
num_cases = raw_input()
num_cases = int(num_cases)
for num in range(num_cases):
s = raw_input()
print is_balanced(s)
It basically checks whether the string typed is balanced or not. If balanced, should return 1 and if not 0.
I tried this:
1
Test string
True
It returns true. I would like it to return 1. How do i do it?
Alternatively you could cast your boolean to an int:
>>>myBoolean = True
>>>int(myBoolean)
1
>>>myBoolean = False
>>>int(myBoolean)
0
Huh? You change the code:
Instead of
return False
write
return 0
and instead of
return len(stack) == 0
write
if len(stack) == 0:
return 1
return 0
The latter 3-liner can be rewritten on a single line, but I chose the above for clarity.
return 1 if len(stack) == 0 else 0
This concisely changes the return value of is_balanced, and is equivalent to:
if len(stack) == 0:
return 1
else:
return 0
Of course you could keep is_balanced unchanged and print (in similar notation):
1 if is_balanced(s) else 0
Just use
print +is_balanced(s)
instead.

Categories