cswork / libraryOpen practice workspace

Coding questions · Snowflake

Evaluate arithmetic expression with variables

This question evaluates implementation skills for a linear-time expression parser and evaluator, covering tokenization, variable substitution, operator precedence and associativity (including unary +/−), parentheses handling, integer arithmetic semantics (division truncation), error detection, and adherence to O(L) time and space constraints.

Implement an expression evaluator for a string expr containing non-negative integers, variables (alphabetic names), operators +, -, , /, parentheses '()' and spaces. Given a dictionary mapping variable names to integer values, compute the signed 64-bit result using standard operator precedence (/ before +-), left-to-right associativity, and support unary +/-. Division truncates toward zero. The evaluator must run in O(L) time where L is the length of expr and use O(L) extra space. Return an error for invalid tokens or mismatched parentheses. Follow-ups: extend to exponentiation '^' (right-associative) and a function max(a,b).

Evaluate Arithmetic Expression with Variables

Implement an expression evaluator. You are given a string expr containing non-negative integers, variables (alphabetic names), the operators + - * /, parentheses (), and spaces, together with a dictionary variables mapping each variable name to an integer value.

Compute and return the result as a signed 64-bit integer using:

  • Standard operator precedence: * and / bind tighter than + and -.
  • Left-to-right associativity for operators of equal precedence.
  • Unary + and - (e.g. -a + 5, +-+5).
  • Integer division that truncates toward zero (so -7 / 2 == -3, not -4).
  • Spaces may appear anywhere and are ignored.

The evaluator must run in O(L) time and O(L) extra space, where L is the length of expr.

If the expression is invalid — an unknown variable, an invalid token, a trailing/dangling operator, or mismatched parentheses — return the string "ERROR" instead of a number.

Return type: the integer result on success, or the string "ERROR" on any invalid input.

Follow-ups to discuss (not graded here): add right-associative exponentiation ^, and a two-argument function max(a, b).

Constraints

  • 0 <= len(expr) <= 10^5
  • Integer operands are non-negative; the final result fits in a signed 64-bit integer (wrap on overflow).
  • Variable names are non-empty alphabetic strings; values are integers.
  • Division truncates toward zero (e.g. -7 / 2 = -3).
  • Invalid input (unknown variable, invalid token, dangling operator, mismatched parentheses) returns the string "ERROR".

Examples

Example 1

Input: ('a + b * 2', {'a': 3, 'b': 4})
Output: 11

Explanation: b*2 = 8 binds before +, then a + 8 = 11 (precedence).

Example 2

Input: ('(a + b) * 2', {'a': 3, 'b': 4})
Output: 14

Explanation: Parentheses force (3+4)=7 first, then 7*2 = 14.

Hints

  1. Use recursive descent with three precedence levels: parse_expr handles + and -, parse_term handles * and /, and parse_factor handles unary signs, parentheses, numbers, and variables.
  2. Track a single index into the string and a skip_spaces helper so whitespace never reaches the operator logic.
  3. For truncate-toward-zero division, compute abs(a) // abs(b) and negate when the operand signs differ — Python's // floors toward negative infinity, which gives the wrong answer for negatives.
  4. After the top-level parse, if the index hasn't reached the end of the string the input had trailing garbage — return ERROR.