Skip to content

Commit 3984f59

Browse files
authored
Merge pull request keon#46 from izanbf1803/master
Added calculator/math_parser.py full code
2 parents 876d5f7 + 45397af commit 3984f59

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ Minimal and clean example implementations of data structures and algorithms in P
4545
- [single_number](bit/single_number.py)
4646
- [subsets](bit/subsets.py)
4747
- [add_without_operator](bit/add_without_operator.py)
48+
- [calculator](calculator)
49+
- [math_parser](calculator/math_parser.py)
4850
- [dfs](dfs)
4951
- [all_factors](dfs/all_factors.py)
5052
- [count_islands](dfs/count_islands.py)
@@ -200,7 +202,6 @@ Minimal and clean example implementations of data structures and algorithms in P
200202
- [design](design)
201203
- [alarm_system](design/alarm_system.md)
202204
- [all_o_one_ds](design/all_o_one_ds.md)
203-
- [calculator](design/calculator.md)
204205
- [excel_table](design/excel_table.md)
205206
- [LRUcache](design/LRUcache.md)
206207
- [nearby_drivers](design/nearby_drivers.md)

calculator/math_parser.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""
2+
Contributed by izanbf1803.
3+
4+
Example:
5+
-------------------------------------------------------------------------------------------------
6+
Code:
7+
| exp = "2452 * (3 * 6.5 + 1) * 6 / 235"
8+
| print("Expression:", exp)
9+
| print("Parsed expression:", mp.parse(exp))
10+
| print("Evaluation result:", mp.evaluate(exp))
11+
12+
Output:
13+
| Expression: 2452 * (3 * 6 + 1) * 6 / 235
14+
| Parsed expression: ['2452', '*', '(', '3', '*', '6', '+', '1', ')', '*', '6', '/', '235']
15+
| Evaluation result: 1189.4808510638297
16+
-------------------------------------------------------------------------------------------------
17+
"""
18+
19+
from collections import deque
20+
import re
21+
22+
numeric_value = re.compile('\d+(\.\d+)?')
23+
24+
__operators__ = "+-/*"
25+
__parenthesis__ = "()"
26+
__priority__ = {
27+
'+': 0,
28+
'-': 0,
29+
'*': 1,
30+
'/': 1,
31+
}
32+
33+
def is_operator(token):
34+
"""
35+
Check if token it's a operator
36+
37+
token Char: Token
38+
"""
39+
return token in __operators__
40+
41+
def higher_priority(op1, op2):
42+
"""
43+
Check if op1 have higher priority than op2
44+
45+
op1 Char: Operation Token 1
46+
op2 Char: Operation Token 2
47+
"""
48+
return __priority__[op1] >= __priority__[op2]
49+
50+
def calc(n2, n1, operator):
51+
"""
52+
Calculate operation result
53+
54+
n2 Number: Number 2
55+
n1 Number: Number 1
56+
operator Char: Operation to calculate
57+
"""
58+
if operator == '-': return n1 - n2
59+
elif operator == '+': return n1 + n2
60+
elif operator == '*': return n1 * n2
61+
elif operator == '/': return n1 / n2
62+
return 0
63+
64+
def apply_operation(op_stack, out_stack):
65+
"""
66+
Apply operation to the first 2 items of the output queue
67+
68+
op_stack Deque (reference)
69+
out_stack Deque (reference)
70+
"""
71+
out_stack.append(calc(out_stack.pop(), out_stack.pop(), op_stack.pop()))
72+
73+
def parse(expression):
74+
"""
75+
Return array of parsed tokens in the expression
76+
77+
expression String: Math expression to parse in infix notation
78+
"""
79+
result = []
80+
current = ""
81+
for i in expression:
82+
if i.isdigit() or i == '.':
83+
current += i
84+
else:
85+
if len(current) > 0:
86+
result.append(current)
87+
current = ""
88+
if i != ' ':
89+
result.append(i)
90+
if len(current) > 0:
91+
result.append(current)
92+
return result
93+
94+
def evaluate(expression):
95+
"""
96+
Calculate result of expression
97+
98+
expression String: The expression
99+
type Type (optional): Number type [int, float]
100+
"""
101+
op_stack = deque() # operator stack
102+
out_stack = deque() # output stack (values)
103+
for token in parse(expression):
104+
if numeric_value.match(token):
105+
out_stack.append(float(token))
106+
elif token == '(':
107+
op_stack.append(token)
108+
elif token == ')':
109+
while len(op_stack) > 0 and op_stack[-1] != '(':
110+
apply_operation(op_stack, out_stack)
111+
op_stack.pop() # Remove remaining '('
112+
else: # is_operator(token)
113+
while len(op_stack) > 0 and is_operator(op_stack[-1]) and higher_priority(op_stack[-1], token):
114+
apply_operation(op_stack, out_stack)
115+
op_stack.append(token)
116+
117+
while len(op_stack) > 0:
118+
apply_operation(op_stack, out_stack)
119+
120+
return out_stack[-1]

0 commit comments

Comments
 (0)