diff --git a/.idea/StringCalculator.iml b/.idea/StringCalculator.iml new file mode 100644 index 0000000000000000000000000000000000000000..d0876a78d06ac03b5d78c8dcdb95570281c6f1d6 --- /dev/null +++ b/.idea/StringCalculator.iml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file diff --git a/src/interfaces.py b/src/interfaces.py new file mode 100644 index 0000000000000000000000000000000000000000..53246cf689694abc6d024abf602d890c37fb07f3 --- /dev/null +++ b/src/interfaces.py @@ -0,0 +1,6 @@ +from abc import ABC, abstractmethod + +class IStringCalculator(ABC): + @abstractmethod + def add(self, numbers: str) -> int: + pass \ No newline at end of file diff --git a/src/stringcalculator.py b/src/stringcalculator.py new file mode 100644 index 0000000000000000000000000000000000000000..fc7e89a3c15a18957c55241afea7767fcad48f34 --- /dev/null +++ b/src/stringcalculator.py @@ -0,0 +1,36 @@ +from src.interfaces import IStringCalculator +import re + + +class StringCalculator(IStringCalculator): + def add(self, numbers: str) -> int: + if not numbers: + return 0 + + if numbers.startswith("//"): + if "\n" not in numbers: + raise ValueError("Ungültiges Format: Nicht vollständig") + delimiter_end_index = numbers.index("\n") + delimiter_part = numbers[2:delimiter_end_index] + if delimiter_part.startswith("[") and delimiter_part.endswith("]"): + delimiter = delimiter_part[1:-1] + else: + delimiter = delimiter_part + numbers = numbers[delimiter_end_index + 1:] + numbers = numbers.replace(delimiter, ",") + + numbers = numbers.replace("\n", ",") + + # Split the string by commas, convert each value to an integer, and sum them up + try: + numbers_list = list(map(int, numbers.split(","))) + except ValueError: + raise ValueError("Ungültiges Zahlenformat: Enthält nicht-numerische Werte") + + negative_numbers = [num for num in numbers_list if num < 0] + if negative_numbers: + raise ValueError(f"Negative nicht erlaubt: {negative_numbers}") + + numbers_list = [num for num in numbers_list if num <= 1000] + + return sum(numbers_list) \ No newline at end of file diff --git a/tests/test_stringclaculator.py b/tests/test_stringclaculator.py new file mode 100644 index 0000000000000000000000000000000000000000..e2e765bd59b8d7d50121700aa53d98082b57a32f --- /dev/null +++ b/tests/test_stringclaculator.py @@ -0,0 +1,85 @@ +# Basis +# Bei Eingabe keiner Zahl soll eine 0 ausgegeben werden +# Bei Eingabe einer 1 soll 1 ausgegeben werden +# Bei Eingabe einer 3,4 soll 7 ausgegeben werden +# Bei Eingabe einer 10,20 soll 30 ausgegeben werden +#Feature1 Längere Zahlenfolge +# Bei Eingabe einer 1,2,3 soll 6 ausgegeben werden +# Bei Eingabe einer 10,20,30,40 soll 100 ausgegeben werden +#Feature2 Neues Trennzeichen neben dem Komma +# Bei Eingabe von 1\n2,3 soll 6 ausgegeben werden +# Bei Eingabe von 10\n20\n30 soll 60 ausgegeben werden +#Feature3 Negative Zahlen ausschließen +# Bei Eingabe von 1, -2, 3 soll ein Error erscheinen "Negative nicht erlaubt: [-2] +# Bei Eingabe von -10\n -20, -30 soll ein Error erscheinen "Negative nicht erlaubt: [-10,-20,30] +#Feature4 Eigene Trennzeichen eingeben +# Bei Eingabe eines neuen Trennzeichen ";" //;\n1;2 soll 3 ausgegeben werden +# Bei Eingabe eines neuen Trennzeichen "x" //-\n7x8\n9 soll 24 ausgegeben werden +# Bei Eingabe eines neuen Trennzeichens ";" ohne vollständigen Ausdrück //;1;2 soll Ungültiges Format: Nicht vollständig +#Feature5 Zahlen größer 1000 nicht erkennen +# Bei Eingabe von 2,1001 soll 2 ausgegeben werden +# Bei Eingabe von 1002, 50200 soll 0 asugegeben werden +#Feature6 Begrenzungszeichen beliebig lang +# Bei Eingabe von //[**]\n1**2**3 soll 6 ausgegeben werden +# Bei Eingabe von //[###]\n10###20###30 soll 60 ausgegeben werden + + +import unittest +from src.interfaces import IStringCalculator +from src.stringcalculator import StringCalculator + +class TestStringCalculator(unittest.TestCase): + def setUp(self): + self.calculator: IStringCalculator = StringCalculator() # Zugriff über das Interface + + def test_add_empty_string(self): + self.assertEqual(self.calculator.add(""), 0) + + def test_add_single_number(self): + self.assertEqual(self.calculator.add("1"), 1) + + def test_add_two_numbers(self): + self.assertEqual(self.calculator.add("10,20"), 30) + + def test_add_multiple_numbers(self): + self.assertEqual(self.calculator.add("1,2,3"), 6) + self.assertEqual(self.calculator.add("10,20,30,40"), 100) + + def test_add_with_newline_separator(self): + self.assertEqual(self.calculator.add("1\n2,3"), 6) + self.assertEqual(self.calculator.add("10\n20\n30"), 60) + + def test_add_single_negative_number(self): + with self.assertRaises(ValueError) as context: + self.calculator.add("1,-2,3") + print(str(context.exception)) + self.assertEqual(str(context.exception), "Negative nicht erlaubt: [-2]") + + def test_add_multiple_negative_numbers(self): + with self.assertRaises(ValueError) as context: + self.calculator.add("-10\n-20,-30") + print(str(context.exception)) + self.assertEqual(str(context.exception), "Negative nicht erlaubt: [-10, -20, -30]") + + def test_add_with_custom_delimiter(self): + self.assertEqual(self.calculator.add("//;\n1;2"), 3) + self.assertEqual(self.calculator.add("//x\n7x8\n9"), 24) + + def test_invalid_custom_delimiter_format(self): + with self.assertRaises(ValueError) as context: + self.calculator.add("//;1;2") + print(str(context.exception)) + + def test_ignore_numbers_greater_than_1000(self): + self.assertEqual(self.calculator.add("2,1001"), 2) + self.assertEqual(self.calculator.add("1002,50200"), 0) + + def test_add_with_custom_delimiter_multiple_characters(self): + self.assertEqual(self.calculator.add("//[**]\n1**2**3"), 6) + self.assertEqual(self.calculator.add("//[###]\n10###20###30"), 60) + +if __name__ == "__main__": + unittest.main() + +# python -m unittest tests.test_stringcalculator +# python -m unittest discover -s tests -v \ No newline at end of file