Skip to content

Commit 13860e3

Browse files
committed
227 Basic Calculator II
1 parent 904cf6b commit 13860e3

File tree

2 files changed

+97
-4
lines changed

2 files changed

+97
-4
lines changed

227 Basic Calculator II py3.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/python3
2+
"""
3+
Implement a basic calculator to evaluate a simple expression string.
4+
5+
The expression string contains only non-negative integers, +, -, *, / operators
6+
and empty spaces . The integer division should truncate toward zero.
7+
8+
Example 1:
9+
10+
Input: "3+2*2"
11+
Output: 7
12+
Example 2:
13+
14+
Input: " 3/2 "
15+
Output: 1
16+
Example 3:
17+
18+
Input: " 3+5 / 2 "
19+
Output: 5
20+
Note:
21+
22+
You may assume that the given expression is always valid.
23+
Do not use the eval built-in library function.
24+
"""
25+
26+
27+
class Solution:
28+
def calculate(self, s: str) -> int:
29+
"""
30+
No brackets. Look at previous operand and operator, when finishing
31+
scanning current operand.
32+
"""
33+
operand = 0
34+
stk = []
35+
prev_op = "+"
36+
for i, c in enumerate(s):
37+
if c.isdigit():
38+
operand = operand * 10 + int(c)
39+
40+
# i == len(s) - 1
41+
delimited = c in ("+", "-", "*", "/") or i == len(s) - 1
42+
if delimited:
43+
if prev_op == "+":
44+
cur = operand
45+
elif prev_op == "-":
46+
cur = -operand
47+
elif prev_op == "*":
48+
cur = stk.pop() * operand
49+
else:
50+
assert prev_op == "/"
51+
# instead of op1 // op2 due to negative handling, -3 // 2 == -2
52+
cur = int(stk.pop() / operand)
53+
54+
stk.append(cur)
55+
prev_op = c
56+
operand = 0
57+
58+
return sum(stk)
59+
60+
def calculate_error(self, s: str) -> int:
61+
"""
62+
cannot use dictionary, since it is eager evaluation
63+
"""
64+
operand = 0
65+
stk = []
66+
prev_op = "+"
67+
for i, c in enumerate(s):
68+
if c.isdigit():
69+
operand = operand * 10 + int(c)
70+
71+
# i == len(s) - 1
72+
delimited = c in ("+", "-", "*", "/") or i == len(s) - 1
73+
if delimited:
74+
cur = {
75+
"+": operand,
76+
"-": -operand,
77+
"*": stk.pop() * operand,
78+
"/": int(stk.pop() / operand), # instead of op1 // op2 due to negative handling, -3 // 2 == -2
79+
}[prev_op]
80+
stk.append(cur)
81+
82+
prev_op = c
83+
operand = 0
84+
85+
return sum(stk)
86+
87+
88+
if __name__ == "__main__":
89+
assert Solution().calculate("3+2*2") == 7

227 Basic Calculator II.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@ def calculate(self, s):
2323
:type s: str
2424
:rtype: int
2525
"""
26-
lst = self.to_list(s)
26+
lst = self.parse(s)
2727
post = self.infix2postfix(lst)
2828
return self.eval_postfix(post)
2929

30-
def to_list(self, s):
30+
def parse(self, s):
31+
"""
32+
return tokens
33+
"""
3134
i = 0
3235
ret = []
3336
while i < len(s):
@@ -47,7 +50,8 @@ def to_list(self, s):
4750
return ret
4851

4952
def infix2postfix(self, lst):
50-
stk = [] # store operators in strictly increasing precedence
53+
# operator stacks rather than operand
54+
stk = [] # stk only stores operators in strictly increasing precedence
5155
ret = []
5256
for elt in lst:
5357
if elt.isdigit():
@@ -100,4 +104,4 @@ def eval_postfix(self, post):
100104

101105

102106
if __name__ == "__main__":
103-
assert Solution().calculate("3+2*2") == 7
107+
assert Solution().calculate("3+2*2") == 7

0 commit comments

Comments
 (0)