From ab1e8e50e99281867047850e36097c924a7a00ec Mon Sep 17 00:00:00 2001 From: Durim Kryeziu Date: Sat, 9 Nov 2024 10:41:26 +0100 Subject: [PATCH] Add 'Simple Math' solution --- README.md | 2 +- settings.gradle | 2 +- simple-math/build.gradle | 8 ++ .../craftsmanshipinsoftware/math/Main.java | 9 ++ .../math/SimpleMath.java | 86 +++++++++++++++++++ .../math/SimpleMathTest.java | 84 ++++++++++++++++++ 6 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 simple-math/build.gradle create mode 100644 simple-math/src/main/java/com/craftsmanshipinsoftware/math/Main.java create mode 100644 simple-math/src/main/java/com/craftsmanshipinsoftware/math/SimpleMath.java create mode 100644 simple-math/src/test/java/com/craftsmanshipinsoftware/math/SimpleMathTest.java diff --git a/README.md b/README.md index ba09fcc..837de8d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Exercises for Programmers: 57 Challenges to Develop Your Coding Skills by Brian - Exercise 2. [Counting the Number of Characters](https://github.com/durimkryeziu/exercises-for-programmers-java/tree/main/characters-count) - Exercise 3. [Printing Quotes](https://github.com/durimkryeziu/exercises-for-programmers-java/tree/main/printing-quotes) - Exercise 4. [Mad Lib](https://github.com/durimkryeziu/exercises-for-programmers-java/tree/main/mad-lib) -- Exercise 5. Simple Math +- Exercise 5. [Simple Math](https://github.com/durimkryeziu/exercises-for-programmers-java/tree/main/simple-math) - Exercise 6. Retirement Calculator **Calculations** diff --git a/settings.gradle b/settings.gradle index 6f894b6..7b7d018 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ rootProject.name = 'exercises-for-programmers-java' -include('saying-hello', 'characters-count', 'printing-quotes', 'mad-lib') +include('saying-hello', 'characters-count', 'printing-quotes', 'mad-lib', 'simple-math') diff --git a/simple-math/build.gradle b/simple-math/build.gradle new file mode 100644 index 0000000..5d05690 --- /dev/null +++ b/simple-math/build.gradle @@ -0,0 +1,8 @@ +plugins { + id 'com.craftsmanshipinsoftware.common-conventions' +} + +dependencies { + testImplementation(libs.assertj.core) + testImplementation(libs.junit.jupiter) +} diff --git a/simple-math/src/main/java/com/craftsmanshipinsoftware/math/Main.java b/simple-math/src/main/java/com/craftsmanshipinsoftware/math/Main.java new file mode 100644 index 0000000..2d1d2e1 --- /dev/null +++ b/simple-math/src/main/java/com/craftsmanshipinsoftware/math/Main.java @@ -0,0 +1,9 @@ +package com.craftsmanshipinsoftware.math; + +public class Main { + + public static void main(String[] args) { + SimpleMath simpleMath = new SimpleMath(System.in, System.out); + simpleMath.printOutput(); + } +} diff --git a/simple-math/src/main/java/com/craftsmanshipinsoftware/math/SimpleMath.java b/simple-math/src/main/java/com/craftsmanshipinsoftware/math/SimpleMath.java new file mode 100644 index 0000000..bc6fef7 --- /dev/null +++ b/simple-math/src/main/java/com/craftsmanshipinsoftware/math/SimpleMath.java @@ -0,0 +1,86 @@ +package com.craftsmanshipinsoftware.math; + +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Objects; +import java.util.Scanner; + +class SimpleMath { + + private final PrintStream printStream; + private final InputStream inputStream; + + SimpleMath(InputStream inputStream, PrintStream printStream) { + Objects.requireNonNull(inputStream, "inputStream must not be null"); + Objects.requireNonNull(printStream, "printStream must not be null"); + this.printStream = printStream; + this.inputStream = inputStream; + } + + void printOutput() { + try (Scanner scanner = new Scanner(inputStream)) { + String firstInput = promptForInput("What is the first number? ", scanner); + int firstNumber = validatedInput(firstInput); + String secondInput = promptForInput("What is the second number? ", scanner); + int secondNumber = validatedInput(secondInput); + if (secondNumber == 0) { + throw new IllegalArgumentException("Cannot divide by zero!"); + } + this.printStream.println(output(firstNumber, secondNumber)); + } + } + + @SuppressWarnings("PMD.SystemPrintln") + private String promptForInput(String prompt, Scanner scanner) { + System.out.print(prompt); + String input = readInput(scanner); + if (input == null || input.isBlank()) { + throw new IllegalArgumentException("Input must not be empty!"); + } + return input; + } + + private String readInput(Scanner scanner) { + return scanner.hasNext() ? scanner.nextLine() : null; + } + + private static int validatedInput(String input) { + try { + int number = Integer.parseInt(input); + if (number < 0) { + throw new IllegalArgumentException("Please enter a positive number! Input: " + number); + } + return number; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Please enter a valid number! Input: " + input, e); + } + } + + private static String output(int firstNumber, int secondNumber) { + return String.format(""" + %d + %d = %d + %d - %d = %d + %d * %d = %d + %d / %d = %d""", + firstNumber, secondNumber, add(firstNumber, secondNumber), + firstNumber, secondNumber, subtract(firstNumber, secondNumber), + firstNumber, secondNumber, multiply(firstNumber, secondNumber), + firstNumber, secondNumber, divide(firstNumber, secondNumber)); + } + + private static int add(int firstNumber, int secondNumber) { + return firstNumber + secondNumber; + } + + private static int subtract(int firstNumber, int secondNumber) { + return firstNumber - secondNumber; + } + + private static int multiply(int firstNumber, int secondNumber) { + return firstNumber * secondNumber; + } + + private static int divide(int firstNumber, int secondNumber) { + return firstNumber / secondNumber; + } +} diff --git a/simple-math/src/test/java/com/craftsmanshipinsoftware/math/SimpleMathTest.java b/simple-math/src/test/java/com/craftsmanshipinsoftware/math/SimpleMathTest.java new file mode 100644 index 0000000..70cb257 --- /dev/null +++ b/simple-math/src/test/java/com/craftsmanshipinsoftware/math/SimpleMathTest.java @@ -0,0 +1,84 @@ +package com.craftsmanshipinsoftware.math; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class SimpleMathTest { + + @ParameterizedTest + @ValueSource(strings = {"", " ", "10\n", "\n5"}) + void inputIsRequired(String input) { + SimpleMath simpleMath = new SimpleMath(new ByteArrayInputStream(input.getBytes()), new PrintStream(new ByteArrayOutputStream())); + + assertThatIllegalArgumentException() + .isThrownBy(simpleMath::printOutput) + .withMessage("Input must not be empty!"); + } + + @Test + void firstInputMustBeANumber() { + SimpleMath simpleMath = new SimpleMath(new ByteArrayInputStream("abc".getBytes()), new PrintStream(new ByteArrayOutputStream())); + + assertThatIllegalArgumentException() + .isThrownBy(simpleMath::printOutput) + .withMessage("Please enter a valid number! Input: abc"); + } + + @Test + void firstNumberMustBePositive() { + SimpleMath simpleMath = new SimpleMath(new ByteArrayInputStream("-10\n5".getBytes()), new PrintStream(new ByteArrayOutputStream())); + + assertThatIllegalArgumentException() + .isThrownBy(simpleMath::printOutput) + .withMessage("Please enter a positive number! Input: -10"); + } + + @Test + void secondInputMustBeANumber() { + SimpleMath simpleMath = new SimpleMath(new ByteArrayInputStream("10\nasdf".getBytes()), new PrintStream(new ByteArrayOutputStream())); + + assertThatIllegalArgumentException() + .isThrownBy(simpleMath::printOutput) + .withMessage("Please enter a valid number! Input: asdf"); + } + + @Test + void secondNumberMustBePositive() { + SimpleMath simpleMath = new SimpleMath(new ByteArrayInputStream("10\n-5".getBytes()), new PrintStream(new ByteArrayOutputStream())); + + assertThatIllegalArgumentException() + .isThrownBy(simpleMath::printOutput) + .withMessage("Please enter a positive number! Input: -5"); + } + + @Test + void secondNumberMustNotBeZero() { + SimpleMath simpleMath = new SimpleMath(new ByteArrayInputStream("10\n0".getBytes()), new PrintStream(new ByteArrayOutputStream())); + + assertThatIllegalArgumentException() + .isThrownBy(simpleMath::printOutput) + .withMessage("Cannot divide by zero!"); + } + + @Test + void sumDifferenceProductAndQuotientIsPrinted() { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + SimpleMath simpleMath = new SimpleMath(new ByteArrayInputStream("10\n5".getBytes()), new PrintStream(outputStream)); + + simpleMath.printOutput(); + + assertThat(outputStream).hasToString(""" + 10 + 5 = 15 + 10 - 5 = 5 + 10 * 5 = 50 + 10 / 5 = 2 + """); + } +}