Last active
July 14, 2016 13:57
-
-
Save fallenflint/6c18b176ed1e970ff6056408457288fd to your computer and use it in GitHub Desktop.
Poland Notation Simple evaluator
This file contains hidden or 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
import unittest | |
class PolandTestCase(unittest.TestCase): | |
def test_basic(self): | |
self.assertEqual(poland_eval('2 4 + 2 *'), 12) | |
def test_space_agnostic(self): | |
res1 = poland_eval('2 4+2*') | |
res2 = poland_eval('2 4 + 2*') | |
self.assertEqual(res1, 12) | |
self.assertEqual(res2, 12) | |
self.assertEqual(res1, res2) | |
def test_unary(self): | |
self.assertEqual(poland_eval('2-'), -2) | |
self.assertEqual(poland_eval('2 +'), 2) | |
OPERATOR_MAP = { | |
# format: | |
# 'operator': ('binary__method', [unary_method]), | |
'+': ('__add__', '__pos__'), | |
'-': ('__sub__', '__neg__'), | |
'/': ('__div__',), | |
'*': ('__mul__',), | |
} | |
OPERATORS = ''.join(OPERATOR_MAP.keys()) | |
def poland_eval(value_string): | |
# Just insert spaces around operators, for splitting | |
for operator in OPERATORS: | |
value_string = value_string.replace(operator, ' %s ' % operator) | |
stack = [] | |
for item in value_string.split(): | |
if item not in OPERATORS: | |
stack.append(float(item)) | |
else: | |
operands = stack[-2:] | |
if len(operands) == 1: | |
try: | |
operator_func = OPERATOR_MAP[item][1] # whether it's unary | |
result = getattr(operands[0], operator_func)() | |
except IndexError: | |
raise ValueError('Unary operator "%s" is not supported!' % item) | |
elif not operands: | |
raise ValueError('Expressions is syntactycally wrong, operator without operand!') | |
else: | |
operator_func = OPERATOR_MAP[item][0] | |
result = getattr(operands[0], operator_func)(operands[1]) | |
stack[-2:] = [result] | |
if len(stack) > 1: | |
raise ValueError('Expression is syntactycally wrong, unexpected estimate!') | |
return stack[0] | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment