Created
March 14, 2019 22:54
-
-
Save inesusvet/f0ac4e665703ceee485a107be1924a8d to your computer and use it in GitHub Desktop.
Coding dojo session result from 2019-03-14
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
""" | |
See https://www.codewars.com/kata/reverse-polish-notation-calculator | |
Your job is to create a calculator which evaluates expressions in Reverse Polish notation. | |
For example expression 5 1 2 + 4 * + 3 - (which is equivalent to 5 + ((1 + 2) * 4) - 3 in normal notation) should evaluate to 14. | |
For your convenience, the input is formatted such that a space is provided between every token. | |
Empty expression should evaluate to 0. | |
Valid operations are +, -, *, /. | |
You may assume that there won't be exceptional situations (like stack underflow or division by zero). | |
""" | |
from operator import add, sub, truediv, mul | |
class Node(object): | |
def __init__(self, val): | |
self.val = val | |
def evaluate(self): | |
return self.val | |
class OpNode(object): | |
def __init__(self, op, a, b): | |
self.op = op | |
self.a = a | |
self.b = b | |
def evaluate(self): | |
res_a = self.a.evaluate() | |
res_b = self.b.evaluate() | |
if self.op == '+': | |
return res_a + res_b | |
if self.op == '-': | |
return res_a - res_b | |
if self.op == '*': | |
return res_a * res_b | |
if self.op == '/': | |
return float(res_a) / res_b | |
else: | |
raise RuntimeError('i am a dumb') | |
def parse_expr(tokens): | |
next_token = tokens.pop() | |
if next_token not in set('*-/+'): | |
val = int(next_token) if next_token.isdigit() else float(next_token) | |
return Node(val) | |
else: | |
op = next_token | |
b = parse_expr(tokens) | |
a = parse_expr(tokens) | |
return OpNode(op, a, b) | |
op_map = {'+': add, '-': sub, '*': mul, '/': truediv} | |
def parse_expr_no_classes(tokens): | |
next_token = tokens.pop() | |
if next_token not in set('*-/+'): | |
val = int(next_token) if next_token.isdigit() else float(next_token) | |
return val | |
else: | |
op = next_token | |
b = parse_expr_no_classes(tokens) | |
a = parse_expr_no_classes(tokens) | |
return op_map[op](a, b) | |
def calc(expr): | |
""" | |
>>> calc("") | |
0 | |
>>> calc("3") | |
3 | |
>>> calc("3.5") | |
3.5 | |
>>> calc("1 3 +") | |
4 | |
>>> calc("1 3 *") | |
3 | |
>>> calc("1 3 -") | |
-2 | |
>>> calc("4 2 /") | |
2 | |
>>> calc("5 1 2 + 4 * + 3 -") | |
14 | |
>>> calc("1 2 + 3 * 4 - 5 /") | |
1 | |
""" | |
if not expr: | |
return 0 | |
tokens = expr.split(' ') | |
res = parse_expr_no_classes(tokens) | |
if res % 1 == 0: | |
return int(res) | |
return res |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment