diff --git a/.github/.keep b/.github/.keep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/serenitydojo/calculator/Calculator.java b/src/main/java/com/serenitydojo/calculator/Calculator.java index 8e88bf0..188c2aa 100644 --- a/src/main/java/com/serenitydojo/calculator/Calculator.java +++ b/src/main/java/com/serenitydojo/calculator/Calculator.java @@ -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 numbers = new Stack<>(); + Stack 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); + } } } + + + diff --git a/src/main/java/com/serenitydojo/calculator/IllegalMathOperatorException.java b/src/main/java/com/serenitydojo/calculator/IllegalMathOperatorException.java new file mode 100644 index 0000000..aba1175 --- /dev/null +++ b/src/main/java/com/serenitydojo/calculator/IllegalMathOperatorException.java @@ -0,0 +1,7 @@ +package com.serenitydojo.calculator; + +public class IllegalMathOperatorException extends RuntimeException { + public IllegalMathOperatorException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/test/java/com/serenitydojo/calculator/WhenDoingMathsTest.java b/src/test/java/com/serenitydojo/calculator/WhenDoingMathsTest.java new file mode 100644 index 0000000..949ed51 --- /dev/null +++ b/src/test/java/com/serenitydojo/calculator/WhenDoingMathsTest.java @@ -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); + } + +} + + + +