I saw that interview question online and gave it a try:
Implement a function that gets a string which represents an arithmethic expression: contains only numbers or the the operators: '+', '-', '*', '/'.
The function returns the calculation result of the arithmethic expression which appears in the string.
This need to be done in O(n) run-time (n is the length of the string) and O(1) extra space.
Example:
"1+2*3" -> 7
I succeed in implementing this (based mainly on some code I found online), but I just have one problem: logic is too complicated. So when reviewing the code, please tell me how can I simplify the logic here.
Here is the code:
class ArithmethicalStatments {
private static int applyOperator(char operand, int firstNum, int secondNum){
switch (operand) {
case '*':
firstNum *= secondNum;
break;
case '/':
firstNum /= secondNum;
break;
case '+':
firstNum = secondNum;
break;
case '-':
firstNum = -secondNum;
break;
}
return firstNum;
}
public static int calc(String str){
int sum = 0;
int lastApplyOpRes = 0;
int lastNum = 0;
int len = str.length();
char prevOperator = '+';
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if (c >= '0' && c <= '9') {
lastNum = lastNum * 10 + c - '0';
continue;
}
lastApplyOpRes = applyOperator(prevOperator, lastApplyOpRes , lastNum);
lastNum = 0;
switch (c) {
case '+':
case '-':
sum += lastApplyOpRes;
lastApplyOpRes = 0;
break;
}
prevOperator = c;
}
lastApplyOpRes = applyOperator(prevOperator, lastApplyOpRes , lastNum);
return sum + lastApplyOpRes;
}
}
In case you want to modify the code- some Junit tests I wrote for your convenience:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class ArithmethicalStatmentsTest {
@Test
void testEmpty() {
assertEquals(0, ArithmethicalStatments.calc(""));
}
@Test
void testOneNum() {
assertEquals(5, ArithmethicalStatments.calc("5"));
}
@Test
void testPlus() {
assertEquals(8, ArithmethicalStatments.calc("5+3"));
}
@Test
void testMul() {
assertEquals(15, ArithmethicalStatments.calc("5*3"));
}
@Test
void testMulPlus() {
assertEquals(8, ArithmethicalStatments.calc("2*3+2"));
}
@Test
void testPlusMul() {
assertEquals(11, ArithmethicalStatments.calc("2+3*3"));
}
@Test
void testPlusMulPlus() {
assertEquals(16, ArithmethicalStatments.calc("2+3+3*3+2"));
}
@Test
void testMinus() {
assertEquals(2, ArithmethicalStatments.calc("5-3"));
}
@Test
void testDivision() {
assertEquals(2, ArithmethicalStatments.calc("6/3"));
}
@Test
void testMinusPlus() {
assertEquals(1, ArithmethicalStatments.calc("2-3+2"));
}
@Test
void testPlusDivide() {
assertEquals(5, ArithmethicalStatments.calc("3+4/2"));
}
@Test
void testAll() {
assertEquals(6, ArithmethicalStatments.calc("2-3+3/3+2*3"));
}
}