CODING CHALLENGE · N°39

Expression Calculator

Medium ParsingRecursionStack

Evaluate an arithmetic expression string — with operator precedence and parentheses — the way an interpreter or spreadsheet does. A tiny recursive-descent parser handles precedence naturally: expressions of terms, terms of factors. Solve it in Python or TypeScript, with hidden tests.

The problem

Implement calc(expr): evaluate a string containing non-negative integers, the operators + - * /, parentheses, and spaces, respecting the usual precedence (* and / bind tighter than + and -) and left-to-right associativity. / is real division. Return the numeric result.

EXAMPLE 1
Input expr = '2+3*4'
Output 14
multiplication first
EXAMPLE 2
Input expr = '(2+3)*4'
Output 20
parentheses override precedence
EXAMPLE 3
Input expr = '2*(3+(4-1))'
Output 12
nested parentheses
CONSTRAINTS
  • Operands are non-negative integers; the expression is well-formed.
  • Precedence: *// before +/-; associativity is left-to-right.
  • Spaces may appear anywhere and should be ignored.
  • Recommended: recursive descent — expr = term (("+"|"-") term)*, term = factor (("*"|"/") factor)*, factor = number | "(" expr ")".
SOLVE IT YOURSELF

Your turn — write it

Edit the stub, hit Run (or ⌘/Ctrl + Enter), and watch the hidden tests. Stuck? the hints are right above and Reveal solution is one click away.

YOUR TASK

Implement calc(expr) as a recursive-descent parser over a position cursor: parse_expr handles + and −, parse_term handles * and /, and parse_factor reads a number or a parenthesised sub-expression. Precedence falls out of the grammar.

HINTS — 4 IDEAS
  1. Strip spaces, then keep a moving index into the string. Each parse function advances it.
  2. factor: if the next char is "(", consume it, parse a full expression, consume ")". Otherwise read a run of digits as an integer.
  3. term: parse a factor, then while the next char is "*" or "/", consume it, parse another factor, and combine.
  4. expr: parse a term, then while the next char is "+" or "-", consume and combine. The grammar gives you precedence for free.
CPython · WebAssembly

Explore the topic

See this challenge alongside everything else on the same subject — handbooks, system designs, algorithms and tools, in one place.