Remove redundant parentheses from an arithmetic expression

Darth.Vader picture Darth.Vader · Aug 23, 2013 · Viewed 31.6k times · Source

This is an interview question, for which I did not find any satisfactory answers on stackoverflow or outside. Problem statement:

Given an arithmetic expression, remove redundant parentheses. E.g. ((a*b)+c) should become a*b+c

I can think of an obvious way of converting the infix expression to post fix and converting it back to infix - but is there a better way to do this?

Answer

Antti Huima picture Antti Huima · Aug 23, 2013

A pair of parentheses is necessary if and only if they enclose an unparenthesized expression of the form X % X % ... % X where X are either parenthesized expressions or atoms, and % are binary operators, and if at least one of the operators % has lower precedence than an operator attached directly to the parenthesized expression on either side of it; or if it is the whole expression. So e.g. in

q * (a * b * c * d) + c

the surrounding operators are {+, *} and the lowest precedence operator inside the parentheses is *, so the parentheses are unnecessary. On the other hand, in

q * (a * b + c * d) + c

there is a lower precedence operator + inside the parentheses than the surrounding operator *, so they are necessary. However, in

z * q + (a * b + c * d) + c

the parentheses are not necessary because the outer * is not attached to the parenthesized expression.

Why this is true is that if all the operators inside an expression (X % X % ... % X) have higher priority than a surrounding operator, then the inner operators are anyway calculated out first even if the parentheses are removed.

So, you can check any pair of matching parentheses directly for redundancy by this algorithm:

Let L be operator immediately left of the left parenthesis, or nil
Let R be operator immediately right of the right parenthesis, or nil
If L is nil and R is nil:
  Redundant
Else:
  Scan the unparenthesized operators between the parentheses
  Let X be the lowest priority operator
  If X has lower priority than L or R:
    Not redundant
  Else:
    Redundant

You can iterate this, removing redundant pairs until all remaining pairs are non-redundant.

Example:

((a * b) + c * (e + f))

(Processing pairs from left to right):

((a * b) + c * (e + f))   L = nil R = nil --> Redundant
^                     ^   
 (a * b) + c * (e + f)    L = nil R = nil --> Redundant
 ^     ^                  L = nil R = + X = * --> Redundant
  a * b  + c * (e + f)    L = * R = nil X = + --> Not redundant
               ^     ^

Final result:

a * b + c * (e + f)