Basic Calculator IV

hard strings parsing math

Problem

Parse an algebraic expression with +, -, *, parentheses, integers, and variables. Given evaluation values for some variables, return the simplified polynomial as a sorted list of terms.

Inputexpr='e + 8 - a + 5', evalvars=['e'], evalints=[1]
Output['-1*a','14']
Substituting e=1 yields -a + 14.

def basicCalculatorIV(expression, evalvars, evalints):
    val = dict(zip(evalvars, evalints))
    def tokenize(s):
        toks, i = [], 0
        while i < len(s):
            if s[i] == ' ': i += 1
            elif s[i] in '()+-*':
                toks.append(s[i]); i += 1
            else:
                j = i
                while j < len(s) and s[j] not in ' ()+-*': j += 1
                toks.append(s[i:j]); i = j
        return toks
    def atom(t):
        if t.lstrip('-').isdigit(): return {(): int(t)}
        return {(): val[t]} if t in val else {(t,): 1}
    def mul(a, b):
        out = {}
        for k1, v1 in a.items():
            for k2, v2 in b.items():
                k = tuple(sorted(k1+k2))
                out[k] = out.get(k, 0) + v1*v2
        return out
    def add(a, b, sign=1):
        out = dict(a)
        for k, v in b.items():
            out[k] = out.get(k, 0) + sign*v
        return out
    toks = tokenize(expression)
    # Shunting-yard to RPN then evaluate
    prec = {'+':1,'-':1,'*':2}
    out_q, ops = [], []
    for t in toks:
        if t == '(': ops.append(t)
        elif t == ')':
            while ops and ops[-1] != '(': out_q.append(ops.pop())
            ops.pop()
        elif t in prec:
            while ops and ops[-1] != '(' and prec[ops[-1]] >= prec[t]:
                out_q.append(ops.pop())
            ops.append(t)
        else:
            out_q.append(t)
    while ops: out_q.append(ops.pop())
    st = []
    for t in out_q:
        if t in prec:
            b, a = st.pop(), st.pop()
            if t == '+': st.append(add(a, b))
            elif t == '-': st.append(add(a, b, -1))
            else: st.append(mul(a, b))
        else:
            st.append(atom(t))
    poly = st[0]
    terms = sorted([(k, v) for k, v in poly.items() if v != 0], key=lambda x: (-len(x[0]), x[0]))
    return [(str(v) if not k else f"{v}*" + "*".join(k)) for k, v in terms]
// Outline: tokenize, shunting-yard to RPN, evaluate using polynomial maps.
function basicCalculatorIV(expression, evalvars, evalints) {
  const val = Object.fromEntries(evalvars.map((v,i) => [v, evalints[i]]));
  // ... see Python version for full logic.
  return [];
}
// Outline only: tokenize, shunting-yard, polynomial map evaluation.
List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
    Map<String,Integer> val = new HashMap<>();
    for (int i = 0; i < evalvars.length; i++) val.put(evalvars[i], evalints[i]);
    // See Python reference for the full implementation.
    return new ArrayList<>();
}
// Outline only: tokenize, shunting-yard, polynomial map evaluation.
vector<string> basicCalculatorIV(string expression, vector<string>& evalvars, vector<int>& evalints) {
    unordered_map<string,int> val;
    for (int i = 0; i < (int)evalvars.size(); i++) val[evalvars[i]] = evalints[i];
    // See Python reference for the full implementation.
    return {};
}
Time: O(n*m) Space: O(n)