Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added .github/.keep
Empty file.
77 changes: 76 additions & 1 deletion src/main/java/com/serenitydojo/calculator/Calculator.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,82 @@
package com.serenitydojo.calculator;

import java.util.Stack;

public class Calculator {

public int evaluate(String expression) {
return 0;
if (expression == null || expression.trim().isEmpty()) {
return 0;
}

String[] tokens = expression.split(" ");
Stack<Integer> numbers = new Stack<>();
Stack<String> operators = new Stack<>();

for (String token : tokens) {
if (isNumber(token)) {
numbers.push(Integer.parseInt(token));
} else if (isOperator(token)) {
while (!operators.isEmpty() && precedence(operators.peek()) >= precedence(token)) {
int secondOperand = numbers.pop();
int firstOperand = numbers.pop();
String operator = operators.pop();
numbers.push(applyOperator(firstOperand, secondOperand, operator));
}
operators.push(token);
} else {
throw new IllegalMathOperatorException("Unsupported operator: " + token);
}
}

while (!operators.isEmpty()) {
int secondOperand = numbers.pop();
int firstOperand = numbers.pop();
String operator = operators.pop();
numbers.push(applyOperator(firstOperand, secondOperand, operator));
}

return numbers.pop();
}

private boolean isNumber(String token) {
try {
Integer.parseInt(token);
return true;
} catch (NumberFormatException e) {
return false;
}
}

private boolean isOperator(String token) {
return "+".equals(token) || "-".equals(token) || "*".equals(token);
}

private int precedence(String operator) {
switch (operator) {
case "*":
return 2;
case "+":
case "-":
return 1;
default:
return 0;
}
}

private int applyOperator(int firstOperand, int secondOperand, String operator) {
switch (operator) {
case "+":
return firstOperand + secondOperand;
case "-":
return firstOperand - secondOperand;
case "*":
return firstOperand * secondOperand;
default:
throw new IllegalArgumentException("Unsupported operator: " + operator);
}
}
}



Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.serenitydojo.calculator;

public class IllegalMathOperatorException extends RuntimeException {
public IllegalMathOperatorException(String message) {
super(message);
}
}
58 changes: 58 additions & 0 deletions src/test/java/com/serenitydojo/calculator/WhenDoingMathsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.serenitydojo.calculator;

import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class WhenDoingMathsTest {
Calculator calculator = new Calculator();

@Test
public void shouldReturnZeroForAnEmptyString() {
assertThat(calculator.evaluate("")).isEqualTo(0);

}


@Test
public void shouldReportNonSupportedOperations() {
assertThatThrownBy(() -> calculator.evaluate("1 ^ 2"))
.isInstanceOf(IllegalMathOperatorException.class)
.hasMessageContaining("Unsupported operator");
}

@Test
public void shouldReturnTheValueOfASingleNumber() {
assertThat(calculator.evaluate("1")).isEqualTo(1);
}

@Test
public void shouldAddTwoNumbers() {
assertThat(calculator.evaluate("1 + 1")).isEqualTo(2);
}

@Test
public void shouldAddThreeNumbers() {
assertThat(calculator.evaluate("1 + 2 + 3")).isEqualTo(6);
}

@Test
public void shouldAlsoSubtract() {
assertThat(calculator.evaluate("10 - 6")).isEqualTo(4);
}

@Test
public void shouldAddAndSubtract() {
assertThat(calculator.evaluate("10 + 5 - 6")).isEqualTo(9);
}

@Test
public void shouldMultiplyNumbers() {
assertThat(calculator.evaluate("10 * 5")).isEqualTo(50);
}

}