validating a postfix with too many operators - python

I am evaluating a postfix expression and I need it to say that the expression cannot be evaluated if there are too many operators one after the other. I understand there will be nothing in the stack so it cannot be evaluated but I don't know how to add it in my code.
I have only added here the code that I feel is necessary. If the code could be kept relatively similar that would be great.
edit: it is now just saying that anything cannot be evaluated
def process(testline,count):
k=[]
for i in range(0,len(testline),1):
if(testline[i].isdigit() == True):
k.append(float(testline[i]))
else:
try:
x = j.pop()
y = j.pop()
except IndexError:
break
if (testline[i]=='*'):
ans = x * y
k.append(ans)
elif (testline[i]=='+'):
ans = x + y
k.append(ans)
elif (testline[i]=='-'):
ans = x - y
k.append(ans)
elif (testline[i]=='/'):
ans = x / y
k.append(ans)
else:
print("Line",count,"is not able to be evaluated")
return
if len(k) != 1:
print("Line",count,"is not able to be evaluated")
else:
print ('Line',count,'result is',k[0])
return
print('Line',count,'result is',k[0])
Right now, the output is:
Line 1 is not able to be evaluated
Line 2 is not able to be evaluated
Line 3 is not able to be evaluated
Line 4 is not able to be evaluated
The input is:
295+*3-
61*7-4*
61*79-15*
6a*7-b*
623-+*-1

You could move your pops to the start of the iteration and surround with try/except to check that you can pop:
for i in range(0,len(testline),1):
if(testline[i].isdigit() == True):
k.append(float(testline[i]))
else:
try:
x = k.pop()
y = k.pop()
except IndexError:
break
if (testline[i]=='*'):
ans = x * y
k.append(ans)
elif (testline[i]=='+'):
ans = x + y
k.append(ans)
elif (testline[i]=='-'):
ans = x - y
k.append(ans)
elif (testline[i]=='/'):
ans = x / y
k.append(ans)
else:
print("Line",count,"is not able to be evaluated")
return
To make it more robust and don't need to add those extra appends I will do:
operators = {'*': lambda x ,y: x * y,
'/': lambda x, y: x / y,
'+': lambda x, y: x + y,
'-': lambda x, y: x - y}
for c in testline:
if c.isdigit():
k.append(float(c))
elif c in operators:
try:
x = k.pop()
y = k.pop()
except IndexError:
break
ans = operators[c](x, y)
k.append(ans)
else:
print("Line",count,"is not able to be evaluated")
return
EDIT: even simpler:
operators = {'*': lambda x ,y: x * y,
'/': lambda x, y: x / y,
'+': lambda x, y: x + y,
'-': lambda x, y: x - y}
for c in testline:
if c.isdigit():
k.append(float(c))
else:
try:
x = k.pop()
y = k.pop()
ans = operators[c](x, y)
k.append(ans)
except IndexError: # Couldn't pop... (empty stack)
break
except KeyError: # char is not a digit and not an operator
print("Line",count,"is not able to be evaluated")
return

Per the OP's desire to keep the original code as unchanged as possible, here's a version of the code that works with the most minimal of changes. The primary change, which is what the OP is asking about specifically, is to add checks for an inadequate number of operands before each arithmetic operation. This code also has the order of operands in calculations reversed where necessary:
def process(testline,count):
k=[]
for i in range(0,len(testline),1):
if(testline[i].isdigit() == True):
k.append(float(testline[i]))
elif (testline[i]=='*'):
if len(k) < 2:
print("Line", count, "is not able to be evaluated. not enough operands")
return
x = k.pop()
y = k.pop()
ans = x * y
k.append(ans)
elif (testline[i]=='+'):
if len(k) < 2:
print("Line", count, "is not able to be evaluated. not enough operands")
return
x = k.pop()
y = k.pop()
ans = x + y
k.append(ans)
elif (testline[i]=='-'):
if len(k) < 2:
print("Line", count, "is not able to be evaluated. not enough operands")
return
x = k.pop()
y = k.pop()
ans = y - x # << reversed operands
k.append(ans)
elif (testline[i]=='/'):
if len(k) < 2:
print("Line", count, "is not able to be evaluated. not enough operands")
return
x = k.pop()
y = k.pop()
ans = y / x # << reversed operands
k.append(ans)
else:
print("Line",count,"is not able to be evaluated")
return
if len(k) != 1:
print("Line",count,"is not able to be evaluated")
return
print('Line',count,'result is',k[0])
With this test code:
lines = [
'295+*3-',
'61*7-4*',
'61*79-15*',
'6a*7-b*',
'(-1)*2',
'623-+*-1',
]
for i in range(len(lines)):
process(lines[i], i + 1)
Resulting output is:
('Line', 1, 'result is', 25.0)
('Line', 2, 'result is', -4.0)
('Line', 3, 'is not able to be evaluated')
('Line', 4, 'is not able to be evaluated')
('Line', 5, 'is not able to be evaluated')
('Line', 6, 'is not able to be evaluated. not enough operands')

Here's my version, which is much like #Tomrikoo's second, but provides a complete answer and addresses a few additional problems with the original code. This code prints either the result or an error in all cases, and deals with the final state in both the case of a valid answer or an invalid stack condition (more than one item on the stack). Also, I reversed the order of application of the operands to be correct (I assume that '42/' should produce 2 rather than 0.5 like all my HP calculators would):
def process(testline, count):
operations = {
'+': lambda x, y: y + x,
'-': lambda x, y: y - x,
'*': lambda x, y: y * x,
'/': lambda x, y: y / x,
}
k = []
for c in testline:
if c.isdigit():
k.append(float(c))
elif c in operations:
if len(k) < 2:
print("Line {}: bad expression '{}' (not enough operands)".format(count, testline))
return
k.append(operations[c](k.pop(), k.pop()))
else:
print("Line {}: unexpected character '{}' in expression '{}'".format(count, c, testline))
return
if len(k) != 1:
print("Line {}: bad expression '{}' (too many operands)".format(count, testline))
else:
print("Line {}: Result: '{}' = {}".format(count, testline, k[0]))
lines = [
'295+*3-',
'61*7-4*',
'61*79-15*',
'6a*7-b*',
'(-1)*2',
'623-+*-1',
]
for i in range(len(lines)):
process(lines[i], i + 1)
Output:
Line 1: Result: '295+*3-' = 25.0
Line 2: Result: '61*7-4*' = -4.0
Line 3: bad expression '61*79-15*' (too many operands)
Line 4: unexpected character 'a' in expression '6a*7-b*'
Line 5: unexpected character '(' in expression '(-1)*2'
Line 6: bad expression '623-+*-1' (not enough operands)

Related

Python: Print largest even number from 3 inputs without using list and max()

The program first asks for 3 integers then computes for the largest even from the set. It will print None if there are no even numbers. We are not allowed to use built-in functions (like max()) and not allowed to import math libraries.
What code can I use so it does not print None when I input x = 11, y = 11, z = 8? The correct output should be 8.
def getMaximum(x,y,z):
if x >= y and x >= z:
return x
elif y >= x and y >= z:
return y
else:
return z
def getLargestEven(x,y,z):
LargestVal = getMaximum(x,y,z)
if LargestVal%2 == 0:
return LargestVal
elif x%2 == 0 and (x > y or x > z):
return x
elif y%2 == 0 and (y > x or y > z):
return y
elif z%2 == 0 and (z > x or z > y):
return z
else:
return None
x = int(input("Enter x: "))
y = int(input("Enter y: "))
z = int(input("Enter z: "))
print("Largest Even:", getLargestEven(x,y,z))
You can also use a simple loop structure to test for the maximum even number among three
def getLargestEven(x,y,z):
max_num = -99999999999999
for num in [x,y,z]:
if num%2==0:
if num>max_num:
max_num = num
return None if max_num ==-99999999999999 else max_num

my results are rounded, i want the full length answer please

Here is my code in Python:
def my_sqrt(a):
x=1
while True:
y=(x+a/x)/2.0
if y==x:
break
x=y
return y
Output I get:
>>> my_sqrt(1.0)
>>> my_sqrt(2)
1.5
Looking to get:
my_sqrt(1.0)-->1.0
my_sqrt(2)-->1.41421356237
return ends the function and returns immediately. It's indented so it's in the loop and runs unconditionally at the end of the first iteration. Dedent it to run after the loop completes due to break:
def my_sqrt(a):
x = 1
while True:
y = (x + a / x) / 2.0
if y == x:
break
x = y
return y
Alternatively, since return ends the function and thus the loop, you don't even need break:
def my_sqrt(a):
x = 1
while True:
y = (x + a / x) / 2.0
if y == x:
return y
x = y

Python, recursion : give all possible tuple combinations who meet a boolean expression

So, for school, I got an exercise on recursion, which goes as follows:
I'm given a string and a random int value 'N'. The string is a boolean expression, for example '3*x - 2* y <0' . The result has to be a list of tuples(x, y), (-N < x < N and -N < y < N), from all the possible tuple combinations who meet the expression. I did this exercise first with for loops etc and that was not so difficult, but then I had to do it recursively, and here's where I got stuck:
As you can see, I just add up x and y by '1' at the end of the code, which will give me all tuple combinations where X and Y are the same. For example, if N = 5, my code only evaluates the combinations (-4,-4), (-3,-3) ... (4,4) but not (-2,1) or (1,3) for example. So my question is: can anyone help me writing a recursive code which evaluates the boolean expression in all the possible tuple combinations?
My code has to be written recursively and I can't use functions as 'itertools' etc, it's not allowed in our school.
**MY CODE:**
def solution(expression, N,x=None,y=None):
if x is None: x = -N + 1
if y is None: y = -N + 1
res = []
if x >= N and y >= N:
return []
if eval(expression) == True:
res.append((x, y))
return res + solution(expression, N, x+1, y+1)
I have modified your code and I think it works now:
UPDATE: I have corrected this expression if x < N - 1 : to that one if x < N - 1 or y < N - 1:
def solution(expression, N, x=None, y=None):
if x is None: x = -N + 1
if y is None: y = -N + 1
res = []
if eval(expression) == True:
res.append((x, y))
# if x < N - 1 :
if x < N - 1 or y < N - 1:
if y < N - 1:
y += 1
else:
x += 1
y = - N + 1
return res + solution(expression, N, x, y)
else:
return res
print(solution('3*x - 2* y <0', 4))
Slightly different approach building on getting permutations for a list and in the end checking the expression. Not the prettiest code but does the job.
results = []
def check(expression, items):
x = y = None
if len(items) == 1:
x = y = items[0]
if eval(expression) and (x, y) not in results:
results.append((x, y))
if len(items) == 2:
x = items[0]
y = items[1]
if eval(expression) and (x, y) not in results:
results.append((x, y))
x = items[1]
y = items[0]
if eval(expression) and (x, y) not in results:
results.append((x, y))
if len(items) > 2:
for i in items:
remaining_elements = [x for x in items if x != i]
check(expression, remaining_elements)
expression = "3*x - 2*y < 0"
N = 4
items = range(-N + 1, N)
check(expression, items)
print(results)

How do I turn a while loop into a recursive method?

I need help turning this while loop into a recursive method? How do I do this?
while z <= len(list):
if z = len(list): #base case
return something
else:
#do something else
z += 1
def func(my_list, z):
if z == len(my_list):
return something
else:
# do something else
return func(my_list, z+1)
z = someValue
print func(my_list, z)
You should not use list as variable name.
z = 1
while z <=5:
if z == 5:
print 'base case'
else:
print 'repeated text'
z += 1
This is translated to recursive code as follows. You can work on your case based on this
def recursion(z):
assert z <= 5
if z == 5:
print 'base case'
else:
print 'repeated text'
recursion(z+1)
recursion(1)
I will implement the recursive function using while loop ---Factorial----
(1)It will call the fact function recursively based on while condition
(2)You can add if or nested if according to your problem statement
def fact(num):
while num>1:
return num*fact(num-1)
else:
return num
result = fact(3)
print(result)
6
condition = lambda n: n >= 3
repetition = lambda n: print(f'{n}: Repeating Line')
termination = lambda n: print(f'{n}: Terminal Line')
def recursive(n):
if condition(n):
repetition(n)
n = recursive(n-1)
else:
termination(n)
return n
def iterative(n):
while condition(n):
repetition(n)
n -= 1
termination(n)
return n
def main():
n = 4
print("Recursion Example")
result = recursive(n)
print(f'result = {result}')
print()
print("Iteration Example")
result = iterative(n)
print(f'result = {result}')
print()
main()
>>> Recursion Example
>>> 4: Repeating Line
>>> 3: Repeating Line
>>> 2: Terminal Line
>>> result = 2
>>>
>>> Iteration Example
>>> 4: Repeating Line
>>> 3: Repeating Line
>>> 2: Terminal Line
>>> result = 2

Are there sideeffects in python using `if a == b == c: pass;`?

if a == b == c:
# do something
Let's assume a, b, c are string variables. Are there any possible side effects if I use the snippet above to execute # do something if and only if all three strings are equal?
I am asking because I have to check three variables against each other and I get many cases:
if a == b == c:
# do something
elif a == b != c:
# do something
elif a != b == c.
# do something
etc...
Perhaps there is a better way to code this?
There should be no side effects until you use it in a such way.
But take care about things like:
if (a == b) == c:
since it will break chaining and you will be comparing True or False and c value).
From the documentation:
Comparisons can be chained arbitrarily; for example, x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
There should be no side effects.
s = set([a, b, c])
if len(s) == 1:
print 'All equal'
elif len(s) == 3:
print 'All different'
else:
l = list(s)
print '%s and %s are different' % (l[0], l[1])
is there any comment on x!=y!=z ?
i could use the stupid way to get a correct answer.
def aligndigits(list):
return ((x, y , z ) for x in list for y in list for z in list if x != y and y != z and x != z )

Categories

Resources