HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Evaluating an expression with integers, +, and *, as well as -, /

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
expressionwithwellandintegersevaluating

Problem

There is a job interview question, and the source of the question is here.

The solution is pretty simple. We just need to split the input string by + and then by *. Then we compute products in a nested loop and sum up all the products.

public class Main {

    // http://www.careercup.com/question?id=4911380140392448
    public static void main(String[] args) {
        String equation = "1*5*4+8*9+16";
        int result = compute(equation);
        System.out.println(result);
    }

    static int compute(String equation) {
        int result = 0;
        String []byPluses = equation.split("\\+");
        for (String multipl : byPluses) {
            String []byMultipl = multipl.split("\\*");
            int multiplResult = 1;
            for (String operand : byMultipl) {
                multiplResult *= Integer.parseInt(operand);
            }
            result += multiplResult;
        }
        return result;
    }

}


But what if I was asked the following question after solving the initial problem:


OK. What would you do if you needed to support not only + and * but also - and /?

The quick solution I thought up is this:

```
package careepcup.fb;

public class Main {

// http://www.careercup.com/question?id=4911380140392448
public static void main(String[] args) {
// An equation with +, -, /, *
String anotherEquation = "154+8*9+16/8-9"; // 85
double another = computeAnother(anotherEquation);
System.out.println(another);
}

static double computeAnother(String equation) {
double result = 0.0;
String noMinus = equation.replace("-", "+-");
String[] byPluses = noMinus.split("\\+");

for (String multipl : byPluses) {
String[] byMultipl = multipl.split("\\*");
double multiplResult = 1.0;
for (String operand : byMultipl) {
if (operand.contains("/")) {
String[] division = operand.split("\\/");

Solution

@tim has covered a bunch of what I was going to add, but here are some additional points:

You should anticipate having whitespace in the input. A "simple" replace-all would suffice:

equation = equation.replaceAll("\\s+", "");


Your solution of converting - to +- is novel, and effective, but it really should have a comment on it explaining that you are going to re-split the String and parse the new - as part of the integer, rather than as an operator. Leaving it as it is required some detective work on how it functions.

Bug: Your system will fail on things like: 1 + 2 * -3 (ignoring the whitespace).

Your inner workings of the * and / is a bit messy, though. A logical progression for your challenge would be to add, say, a % operator.... which would require a complicated change.

Operators of equal precedence should be handled together. treating specially when compared to / makes it awkward because you have to test all combinations inside the breakdown....

I would suggest using a smarter split expression, one that splits on the gaps between the operators and the values...:

String[] parts = operand.split("(?=[/*])|(?<=[/*])");


With the above regex, you will get for example:

1/2*773 -> [1, /, 2, *, 773]


The way the regex works is that it looks for two things (the regex is in two parts - using "lookaround" expressions)....

  • (?=[/]) - A positive zero-width look-ahead - This says: find any gap between two characters where the next character is a / or .



  • (?



Put them together with an or condition, it says: split the input on the gaps before and after
/ or *`.
Now, you can just initialize the result to index-1, and then loop through the rest.... :

double result = Double.parseDouble(parts[0]);

for (int i = 1; i < parts.length; i += 2) {
    String op = parts[i];
    double val = Double.parseDouble(parts[i+1]);
    switch (op) {
        case "*" :
            result *= val;
            break;
        case "/" :
            result /= val;
            break;
    }
}
return result;

Code Snippets

equation = equation.replaceAll("\\s+", "");
String[] parts = operand.split("(?=[/*])|(?<=[/*])");
1/2*773 -> [1, /, 2, *, 773]
double result = Double.parseDouble(parts[0]);

for (int i = 1; i < parts.length; i += 2) {
    String op = parts[i];
    double val = Double.parseDouble(parts[i+1]);
    switch (op) {
        case "*" :
            result *= val;
            break;
        case "/" :
            result /= val;
            break;
    }
}
return result;

Context

StackExchange Code Review Q#84763, answer score: 9

Revisions (0)

No revisions yet.