Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Program: eval_infix(s) Method 1. The current infixToPostfix(s) method from the b

ID: 3694073 • Letter: P

Question

Program: eval_infix(s) Method

1. The current infixToPostfix(s) method from the book has the problem that it will not read numbers of more than one digit or float numbers such as 98.15. ( easy way to handle multi-digit float numbers is to write a function to return true if a string contains a valid float number, and then use that function to check if the string is a valid number in infixToPostfix and in postfixEval.

2. The postfixEval(s) has the same problem, it will not correctly process multi digit numbers or work with floats.

Start from this start code eval_infix.py and do the following:

fix the book methods infixToPostfix and postfixEval to convert string tokens that are operators to float correctly

write another new method called eval_infix(s) that will receive a string with a infix expressions where all the tokens already have a space between them and inside the method, call infixToPostfix to get the postfix string, and then callpostfixEval with that string to get a final float result and then return that.

eval_infix(s) will basically take a infix expression string and return the result of the expression as a float.

The test code included at the end of the file should all pass when your modifications are correct. (it will not indicate any errors)

Make sure to drag the pythonds folder to the same folder as your .py file you are working with (or you can drag it to the C:Python34 folder on a PC), putting it in the search path for python imports)

In PyCharm, drag the pythonds folder from file manager to the project explorer area project area to copy the folder to your project

Once your modified code is passing all the tests, upload it here and submit for grading.

NOTEs: Ideas you can try to determine if a string is a valid float:

try converting it to a float with float(string) inside a try escape block, and return true or false accordingly

loop though each character in the string and check that they are a digit or a period, and that there are not more than one period. You can also check if the string starts with a + or -, which is legal

Do a little research into the pattern matching module regular expressions in python:

https://developers.google.com/edu/python/regular-expressions#basic-patterns

http://www.tutorialspoint.com/python/python_reg_expressions.htm

and use the match function to test if there is a pattern that matches a float:
see http://www.regular-expressions.info/floatingpoint.html

from pythonds.basic.stack import Stack

def infixToPostfix(infixexpr): # fix this code to do floats

prec = {}

prec["*"] = 3

prec["/"] = 3

prec["+"] = 2

prec["-"] = 2

prec["("] = 1

opStack = Stack()

postfixList = []

tokenList = infixexpr.split()

for token in tokenList:

if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":

postfixList.append(token)

elif token == '(':

opStack.push(token)

elif token == ')':

topToken = opStack.pop()

while topToken != '(':

postfixList.append(topToken)

topToken = opStack.pop()

else:

while (not opStack.isEmpty()) and

   (prec[opStack.peek()] >= prec[token]):

postfixList.append(opStack.pop())

opStack.push(token)

while not opStack.isEmpty():

postfixList.append(opStack.pop())

return " ".join(postfixList)

def postfixEval(postfixExpr): # also fix this to do floats

operandStack = Stack()

tokenList = postfixExpr.split()

for token in tokenList:

if token in "0123456789":

operandStack.push(int(token))

else:

operand2 = operandStack.pop()

operand1 = operandStack.pop()

result = doMath(token,operand1,operand2)

operandStack.push(result)

return operandStack.pop()

def doMath(op, op1, op2):

if op == "*":

return op1 * op2

elif op == "/":

return op1 / op2

elif op == "+":

return op1 + op2

else:

return op1 - op2

def eval_infix(s):

'''to do replace this line with your code '''

### Keep all this code AS-IS, do not modify

### This code runs a unit test and will report errors

### when it detects your result is different than the expected result

###

### do not modify the following, if you get an error, it is in

### your code

import math

import unittest

class TestEvalInfix(unittest.TestCase):

def setUp(self):

self.tests = tests = (

"1", "1 + 2", "3 * 2 + 1", "1 + 2 * 3",

"( 0.5 + 1.5 + 2.0 )", "( 2.0 * 3 ) - 1",

"( 1.0 - .5 ) * ( 2.5 / .5 )", "( 1 ) * ( .33333333 ) * ( 3.00000 )"

)

def test_expressions(self):

for expression in self.tests:

print("Testing expression '%s'" % (expression))

expected = eval(expression)

got = eval_infix(expression)

self.assertAlmostEqual( got, expected, "got: "+ str(got) + " expect: " + str(expected) )

# "Expression '%s' resulted in value %.4f, expected value was %.4f" %

# (expression,got,expected) )

if __name__ == '__main__':

print("STARTING TESTS")

unittest.main()

Explanation / Answer

def push_stack(stackArr,ele): stackArr.append(ele) def pop_stack(stackArr): return stackArr.pop() def isOperand(who): if(not(isOperator(who)) and (who != "(") and (who != ")")): return 1 return 0 def isOperator(who): if(who == "+" or who == "-" or who == "*" or who == "/" or who == "^"): return 1 return 0 def topStack(stackArr): return(stackArr[len(stackArr)-1]) def isEmpty(stackArr): if(len(stackArr) == 0): return 1 return 0 def prcd(who): if(who == "^"): return(5) if((who == "*") or (who == "/")): return(4) if((who == "+") or (who == "-")): return(3) if(who == "("): return(2) if(who == ")"): return(1) def ip(infixStr,postfixStr = [],retType = 0): postfixStr = [] stackArr = [] postfixPtr = 0 tempStr = infixStr infixStr = [] infixStr = strToTokens(tempStr) for x in infixStr: if(isOperand(x)): postfixStr.append(x) postfixPtr = postfixPtr+1 if(isOperator(x)): if(x != "^"): while((not(isEmpty(stackArr))) and (prcd(x)