Skip to content

Commit 07e1520

Browse files
authored
Update basic-calculator-iv.py
1 parent 28a1893 commit 07e1520

1 file changed

Lines changed: 72 additions & 56 deletions

File tree

Python/basic-calculator-iv.py

Lines changed: 72 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
# Time: O(m + n^3 * logn)
2-
# Space: O(m + n)
1+
# Time: +: O(d * t), t is the number of terms, d is the average degree of terms
2+
# -: O(d * t)
3+
# *: O(d * t^2)
4+
# eval: O(d * t)
5+
# to_list: O(d * tlogt)
6+
# Space: O(e + d * t), e is the number of evalvars
37

48
class Poly(collections.Counter):
59
def __init__(self, expr=""):
@@ -19,27 +23,45 @@ def __sub__(self, other):
1923
return self
2024

2125
def __mul__(self, other):
26+
def merge(k1, k2):
27+
result = []
28+
i, j = 0, 0
29+
while i != len(k1) or j != len(k2):
30+
if j == len(k2):
31+
result.append(k1[i])
32+
i += 1
33+
elif i == len(k1):
34+
result.append(k2[j])
35+
j += 1
36+
elif k1[i] < k2[j]:
37+
result.append(k1[i])
38+
i += 1
39+
else:
40+
result.append(k2[j])
41+
j += 1
42+
return result
43+
2244
result = Poly()
2345
for k1, v1 in self.items():
2446
for k2, v2 in other.items():
25-
result.update({tuple(sorted(k1+k2)): v1*v2})
47+
result.update({tuple(merge(k1, k2)): v1*v2})
2648
return result
2749

28-
def evaluate(self, lookup):
50+
def eval(self, lookup):
2951
result = Poly()
30-
for k, c in self.items():
31-
poly = []
32-
for token in k:
33-
if token in lookup:
34-
c *= lookup[token]
52+
for polies, c in self.items():
53+
key = []
54+
for var in polies:
55+
if var in lookup:
56+
c *= lookup[var]
3557
else:
36-
poly.append(token)
37-
result[tuple(poly)] += c
58+
key.append(var)
59+
result[tuple(key)] += c
3860
return result
3961

4062
def to_list(self):
4163
return ["*".join((str(v),) + k) \
42-
for k, v in sorted(self.items(), key=lambda(k, v): (-len(k), k, v)) \
64+
for k, v in sorted(self.items(), key=lambda(k, _): (-len(k), k)) \
4365
if v]
4466

4567

@@ -51,48 +73,42 @@ def basicCalculatorIV(self, expression, evalvars, evalints):
5173
:type evalints: List[int]
5274
:rtype: List[str]
5375
"""
76+
def compute(operands, operators):
77+
left, right = operands.pop(), operands.pop()
78+
op = operators.pop()
79+
if op == '+':
80+
operands.append(left + right)
81+
elif op == '-':
82+
operands.append(left - right)
83+
elif op == '*':
84+
operands.append(left * right)
85+
elif op == '/':
86+
operands.append(left / right)
87+
88+
def parse(s):
89+
if not s:
90+
return Poly()
91+
operands, operators = [], []
92+
operand = ""
93+
for i in reversed(xrange(len(s))):
94+
if s[i].isalnum():
95+
operand += s[i]
96+
if i == 0 or not s[i-1].isalnum():
97+
operands.append(Poly(operand[::-1]))
98+
operand = ""
99+
elif s[i] == ')' or s[i] == '*':
100+
operators.append(s[i])
101+
elif s[i] == '+' or s[i] == '-':
102+
while operators and operators[-1] == '*':
103+
compute(operands, operators)
104+
operators.append(s[i])
105+
elif s[i] == '(':
106+
while operators[-1] != ')':
107+
compute(operands, operators)
108+
operators.pop()
109+
while operators:
110+
compute(operands, operators)
111+
return operands[-1]
112+
54113
lookup = dict(itertools.izip(evalvars, evalints))
55-
56-
def do_operator(left, right, operator):
57-
if operator == '+': return left + right
58-
if operator == '-': return left - right
59-
if operator == '*': return left * right
60-
raise
61-
62-
def parse(expr):
63-
operands = []
64-
operators = []
65-
i = 0
66-
while i < len(expr):
67-
if expr[i] == '(':
68-
cnt = 0
69-
for j in xrange(i, len(expr)):
70-
if expr[j] == '(': cnt += 1
71-
if expr[j] == ')': cnt -= 1
72-
if cnt == 0: break
73-
operands.append(parse(expr[i+1:j]))
74-
i = j
75-
elif expr[i].isalnum():
76-
for j in xrange(i, len(expr)):
77-
if expr[j] == ' ':
78-
operands.append(Poly(expr[i:j]))
79-
break
80-
else:
81-
operands.append(Poly(expr[i:]))
82-
i = j
83-
elif expr[i] in '+-*':
84-
operators.append(expr[i])
85-
i += 1
86-
87-
for i in reversed(xrange(len(operators))):
88-
if operators[i] == '*':
89-
operands[i] = do_operator(operands[i], operands.pop(i+1), \
90-
operators.pop(i))
91-
92-
if not operands: return Poly()
93-
result = operands[0]
94-
for i, operator in enumerate(operators, 1):
95-
result = do_operator(result, operands[i], operator)
96-
return result
97-
98-
return parse(expression).evaluate(lookup).to_list()
114+
return parse(expression).eval(lookup).to_list()

0 commit comments

Comments
 (0)