Question: file exp_eval.py has been given below, create tests in file exp_eval_tests.py for the functions postfix_eval and infix_to_postfix file exp_eval_tests.py outline to start off has been
file exp_eval.py has been given below, create tests in file exp_eval_tests.py for the functions postfix_eval and infix_to_postfix
file exp_eval_tests.py outline to start off has been given below too, please use it
100% coverage is required for the tests
CODE IS IN PYTHON ONLY
#exp_eval_tests.py
from __future__ import annotations
import unittest
from exp_eval import infix_to_postfix, postfix_eval
class Tests(unittest.TestCase):
def test_postfix_eval_01(self):
# NOTE: When testing for equality between values that could be
# floats, we should use assertAlmostEqual
self.assertAlmostEqual(postfix_eval("1 2 +"), 3)
create tests for function in file exp_eval.py
def test_infix_to_postfix_01(self):
# NOTE: But for strings, we should stick with assertEqual
self.assertEqual(infix_to_postfix("1 + 2"), "1 2 +")
# TODO: add more tests!
if __name__ == "__main__":
unittest.main()
#exp_eval.py
from __future__ import annotations
from array_stack import ArrayStack, empty_stack, push, pop, peek, is_empty, size
# NOTE: You'll probably need to import some things from array_stack.
def postfix_eval(input_string: str) -> float:
"""Evaluate the given RPN expression.
Args:
input_string: an RPN expression
Returns:
The result of the expression evaluation
Raises:
ValueError: if the input is not well-formed
ZeroDivisionError: if the input would cause division by zero
"""
# Split the input string into tokens
tokens = input_string.split()
# Initialize an empty stack
stack = empty_stack()
# Process the expression from left to right
for token in tokens:
if token.isdigit():
# If the token is a number, push it onto the stack
push(stack, float(token))
elif token in "+-*/":
# If the token is an operator, pop the required number of values from the stack
try:
op2 = pop(stack)
op1 = pop(stack)
except IndexError:
raise ValueError("insufficient operands")
# Perform the operation
if token == "+":
result = op1 + op2
elif token == "-":
result = op1 - op2
elif token == "*":
result = op1 * op2
elif token == "/":
if op2 == 0:
raise ZeroDivisionError("division by zero")
result = op1 / op2
# Push the result back onto the stack
push(stack, result)
else:
# If the token is neither a valid operand nor a valid operator
raise ValueError("invalid token")
# Return the last value remaining on the stack
if size(stack) != 1:
raise ValueError("too many operands")
return pop(stack)
def infix_to_postfix(input_string: str) -> str:
"""Convert the given infix string to RPN.
Args:
input_string: an infix expression
Returns:
The equivalent expression in RPN
"""
operator_stack = ArrayStack()
operand_stack = ArrayStack()
tokens = input_string.split()
for token in tokens:
if token.isdigit():
push(operand_stack, token)
elif token in "+-*/":
while (not is_empty(operator_stack)) and (peek(operator_stack) in "+-*/") and (precedence(peek(operator_stack)) >= precedence(token)):
push(operand_stack, pop(operator_stack))
push(operator_stack, token)
else:
raise ValueError("Invalid token")
while not is_empty(operator_stack):
push(operand_stack, pop(operator_stack))
postfix_expression = " ".join(list(reversed([str(x) for x in operand_stack.array if x is not None])))
return postfix_expression
def precedence(operator: str) -> int:
if operator in "+-":
return 1
elif operator in "*/":
return 2
else:
raise ValueError("Invalid operator")
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
