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
48class 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