Skip to content

Instantly share code, notes, and snippets.

@nwizugbesamson
Created December 22, 2022 17:38
Show Gist options
  • Save nwizugbesamson/f21ac69ad420c9c094e68cbf58958b53 to your computer and use it in GitHub Desktop.
Save nwizugbesamson/f21ac69ad420c9c094e68cbf58958b53 to your computer and use it in GitHub Desktop.
## 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