Created
December 22, 2022 17:38
-
-
Save nwizugbesamson/f21ac69ad420c9c094e68cbf58958b53 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## SHUNT YARD ALGORITHM | |
class ShuntCalc: | |
def __init__(self): | |
## available operators | |
self.operators = { | |
'-': [self._process_minus, 1], | |
'+': [self._process_plus, 1], | |
'*': [self._process_times, 2], | |
'/': [self._process_divide, 2], | |
'**':[ self._process_pow, 3] } | |
## split expression by whitespace | |
def _tokenize(self, expression: str): | |
return expression.split() | |
## operation methods | |
def _process_minus(self, stack): | |
top_token = stack.pop() | |
first_token = stack.pop() | |
result = first_token - top_token | |
stack.push(result) | |
def _process_plus(self, stack): | |
top_token = stack.pop() | |
first_token = stack.pop() | |
result = first_token + top_token | |
stack.push(result) | |
def _process_times(self, stack): | |
top_token = stack.pop() | |
first_token = stack.pop() | |
result = first_token * top_token | |
stack.push(result) | |
def _process_divide(self, stack): | |
top_token = stack.pop() | |
first_token = stack.pop() | |
result = first_token / top_token | |
stack.push(result) | |
def _process_pow(self, stack): | |
top_token = stack.pop() | |
first_token = stack.pop() | |
result = first_token ** top_token | |
stack.push(result) | |
## evaluate postfix expression | |
def _evaluate_postfix(self, expression:str): | |
"""evaluate arithimethic expression in postfix format | |
Args: | |
expression (_str_): _expression to evaluate, must be in postfix format_ | |
Returns: | |
_float_: _result_ | |
""" | |
## stack object (LIFO) | |
stack = Stack() | |
expression = self._tokenize(expression) | |
## numbers get added to stack | |
## pulled out on encountering an operator | |
## result of operation is pushed back into stack to continue | |
for token in expression: | |
if token in self.operators: | |
self.operators[token][0](stack) | |
else: | |
stack.push(float(token)) | |
result = stack.pop() | |
return result | |
## methods for shantyard function | |
## handling open parenthesis in expression | |
def _process_open_parenthesis(self, stack: Stack): | |
stack.push('(') | |
## handling close of parenthesis in expression | |
def _process_close_parenthesis(self, stack: Stack, postfix: list): | |
while stack.peek() != '(': | |
postfix.append(stack.pop()) | |
stack.pop() | |
def _process_operator(self, stack: Stack, postfix: list, operator: str): | |
while len(stack) > 0 and stack.peek() in self.operators and self.operators[stack.peek()][1] >= self.operators[operator][1]: | |
postfix.append(stack.pop()) | |
stack.push(operator) | |
def _process_number(self, postfix: list, number: str): | |
postfix.append(number) | |
def _infix_to_postfix(self, expression): | |
tokens = self._tokenize(expression) | |
stack = Stack() | |
postfix = [] | |
for token in tokens: | |
if token == '(': | |
self._process_open_parenthesis(stack) | |
elif token == ')': | |
self._process_close_parenthesis(stack, postfix) | |
elif token in self.operators: | |
self._process_operator(stack, postfix, token) | |
else: | |
self._process_number(postfix, token) | |
while len(stack) > 0: | |
postfix.append(stack.pop()) | |
postfix = ' '.join(postfix) | |
return postfix | |
def evaluate(self, expression): | |
postfix_exp = self._infix_to_postfix(expression) | |
result = self._evaluate_postfix(postfix_exp) | |
return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment