Skip to content
Snippets Groups Projects
Commit 6db3ea0b authored by Azoth275's avatar Azoth275
Browse files

Update

parent 3e98032c
No related branches found
No related tags found
No related merge requests found
from src.interfaces import ICounter
class Counter(ICounter):
def count_ed(self, s: str) -> int:
"""Zählt die Anzahl der Buchstaben 'E' und 'D' in einem String (Case-Insensitive)."""
s = s.upper()
return s.count("D") + s.count("E")
from src.interfaces import IRomanConverter
def int_to_roman(num: int) -> str:
"""Konvertiert eine Dezimalzahl in eine römische Zahl."""
val = [
1000, 900, 500, 400,
100, 90, 50, 40,
10, 9, 5, 4,
1
]
syb = [
"M", "CM", "D", "CD",
"C", "XC", "L", "XL",
"X", "IX", "V", "IV",
"I"
]
roman_num = ''
i = 0
while num > 0:
for _ in range(num // val[i]):
roman_num += syb[i]
num -= val[i]
i += 1
return roman_num
class RomanConverter(IRomanConverter):
def roman_to_int(self, s: str) -> int:
"""Konvertiert eine römische Zahl (String) in eine Dezimalzahl."""
roman_values = {
'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000
}
total = 0
prev_value = 0
# Iteriere über die Zeichen der römischen Zahl von rechts nach links
for char in reversed(s.upper()):
value = roman_values.get(char)
if value is None:
raise ValueError(f"Ungültiges Zeichen '{char}' in der römischen Zahl.")
if value < prev_value:
total -= value
else:
total += value
prev_value = value
return total
from src.calculator import Calculator
from src.Count_ED import Counter
from src.RomanConverter import RomanConverter, int_to_roman
from src.string_calculator import StringCalculator
if __name__ == "__main__":
# Erstelle eine Instanz der Calculator-Klasse
calc = Calculator()
# Eine Liste von Test-Ausdrücken, die überprüft werden sollen
test_expressions = [
"2+3", # Einfacher Additionstest
"10-4/2", # Test mit Division und Subtraktion
"(3+5)*2", # Komplexerer Ausdruck mit Klammern
"3++5", # Ungültiger Ausdruck (doppelte Operatoren)
"3--5", # Ungültiger Ausdruck (doppelte Operatoren)
"10*/2", # Ungültiger Ausdruck (Operatorenkombinationen)
"5/0", # Division durch Null (Fehler)
"(3+5))", # Ungültiger Ausdruck (zu viele Klammern)
"abc", # Ungültiger Ausdruck (nur Buchstaben)
"-3*-3" # Gültiger Ausdruck mit Vorzeichen
]
# Schleife, um alle Test-Ausdrücke zu durchlaufen
for expr in test_expressions:
try:
# Versuche, den Ausdruck zu berechnen und gebe das Ergebnis aus
print(f"Eingabe: '{expr}' → Ausgabe: {calc.calculate(expr)}")
except Exception as e:
# Wenn ein Fehler auftritt, gebe die Fehlermeldung aus
print(f"Eingabe: '{expr}' → Fehler: {e}")
print("______________________________________________________________")
if __name__ == "__main__":
counter = Counter()
test_strings = ["Decker", "", "Hallo", "Der Esel", "D", "E", "d", "e"]
for string in test_strings:
print(f"Eingabe: '{string}' → Ausgabe: {counter.count_ed(string)}")
print("______________________________________________________________")
if __name__ == "__main__":
converter = RomanConverter()
# Test römische Zahl in Dezimalzahl umwandeln
print("Test römische Zahl in Dezimalzahl umwandeln")
print(converter.roman_to_int("MCMXCIV")) # Ausgabe: 1994
print(converter.roman_to_int("XIV")) # Ausgabe: 14
print(converter.roman_to_int("CDXLIV")) # Ausgabe: 444
# Test Dezimalzahl in römische Zahl umwandeln
print("Test Dezimalzahl in römische Zahl umwand")
print(int_to_roman(1994)) # Ausgabe: MCMXCIV
print(int_to_roman(14)) # Ausgabe: XIV
print(int_to_roman(444)) # Ausgabe: CDXLIV
print("______________________________________________________________")
if __name__ == "__main__":
# ==== StringCalculator ====
sc = StringCalculator()
test_inputs = [
"1,2,3", # 6
"1\n2,3", # 6
"//;\n1;2", # 3
"//[***]\n1***2***3", # 6
"2,1001", # 2 (1001 wird ignoriert)
"-1,2,-3", # Exception
"", # 0
" ", # 0
]
for s in test_inputs:
try:
print(f"Eingabe: '{s}' → Ausgabe: {sc.add(s)}")
except Exception as e:
print(f"Eingabe: '{s}' → Fehler: {e}")
print("______________________________________________________________")
\ No newline at end of file
import re
from src.interfaces import ICalculator
class Calculator(ICalculator):
"""Ein Taschenrechner, der mathematische Ausdrücke berechnet."""
def calculate(self, expression: str) -> float:
"""Berechnet einen mathematischen Ausdruck als String und überprüft auf ungültige Eingaben."""
try:
# Entfernt überflüssige Leerzeichen
expression = expression.replace(" ", "")
# Nur erlaubte Zeichen (Zahlen, Operatoren, Klammern) und Zahlen mit Vorzeichen
if not re.match(r'^[0-9+\-*/().]+$', expression):
raise ValueError("Ungültige Zeichen im Ausdruck.")
# Überprüfung auf doppelte Operatoren, aber keine Vorzeichen wie -* oder -+
# Hier wird jetzt auch sichergestellt, dass -3*-3 gültig bleibt
if re.search(r'(?<!\d)[+\-*/]{2,}', expression): # Erfasst auch doppelte Operatoren wie ++, --, **, etc.
raise SyntaxError("Ungültige doppelte Operatoren im Ausdruck.")
# Sicherstellen, dass Klammern ausgeglichen sind
if expression.count("(") != expression.count(")"):
raise ValueError("Fehlende oder zu viele Klammern.")
# Sicherstellen, dass der Ausdruck nicht mit einem Operator beginnt oder endet,
# aber das Minuszeichen als Teil der Zahl akzeptiert wird
if re.match(r'^[*/]', expression) or re.match(r'[*/]$', expression): # Weitere Kontrolle
raise ValueError("Der Ausdruck darf nicht mit einem Operator beginnen oder enden.")
# Evaluierung des mathematischen Ausdrucks mit eval()
result = eval(expression, {"__builtins__": None}, {})
# Sicherstellen, dass das Ergebnis numerisch ist
if isinstance(result, (int, float)):
return float(result)
else:
raise ValueError("Ungültiger Ausdruck.")
except ZeroDivisionError:
raise ZeroDivisionError("Division durch Null ist nicht erlaubt.")
except (SyntaxError, TypeError, NameError) as e:
raise ValueError(f"Ungültiger mathematischer Ausdruck: {str(e)}")
from abc import ABC, abstractmethod
# Definition des Interfaces für den StringCalculator
class IStringCalculator(ABC):
@abstractmethod
def add(self, numbers: str) -> int:
"""
Addiert beliebig viele Zahlen, die durch Kommas getrennt sind.
Leere oder nur aus Leerzeichen bestehende Einträge werden ignoriert.
:param numbers: String mit Zahlen (z.B. "1,2,3")
:return: Summe der Zahlen als int
"""
pass
class ICounter(ABC):
@abstractmethod
def count_ed(self, s: str) -> int:
"""Zählt die Buchstaben 'E' und 'D' in einem String (Case-Insensitive)."""
pass
class IRomanConverter(ABC):
@abstractmethod
def roman_to_int(self, s: str) -> int:
"""Konvertiert eine römische Zahl (String) in eine Dezimalzahl."""
pass
class ICalculator(ABC):
@abstractmethod
def calculate(self, expression: str) -> float:
pass
\ No newline at end of file
# Implementierung von IStringCalculator
from src.interfaces import IStringCalculator
class StringCalculator(IStringCalculator):
def add(self, numbers: str) -> int:
"""
Addiert beliebig viele Zahlen, getrennt durch Kommas, Zeilenumbrüche
oder einen benutzerdefinierten Delimiter.
Leere oder whitespace-only Einträge werden ignoriert.
Beispiele:
- "" → 0
- "1" → 1
- "1,2" → 3
- "1,2,3,4,5" → 15
- "1,,2" → 3
- "1, ,2" → 3
- ",,1,,2,,," → 3
:param numbers: Zahlen als String, getrennt durch Komma
:return: Summe der gültigen Zahlen als int
"""
if not numbers:
return 0
delimiter = ","
if numbers.startswith("//"):
header, numbers = numbers.split("\n", 1)
# Mehrzeichen-Delimiter: z.B. //[***]
if header.startswith("//[") and header.endswith("]"):
delimiter = header[3:-1] # Extrahiere z.B. "***"
else:
delimiter = header[2:] # Einzeichen-Delimiter
# Ersetze \n durch Komma (Standard)
numbers = numbers.replace("\n", ",")
# Delimiter ersetzen durch Komma (evtl. mehrere Zeichen)
numbers = numbers.replace(delimiter, ",")
number_list = numbers.split(",")
# Ignoriere leere oder whitespace-only Einträge
cleaned_numbers = [
int(n.strip()) for n in number_list if n.strip() != ""
]
# Negativ-Prüfung
negatives = [n for n in cleaned_numbers if n < 0]
if negatives:
raise ValueError(f"negatives not allowed: {', '.join(map(str, negatives))}")
# Zahlen > 1000 ignorieren
cleaned_numbers = [n for n in cleaned_numbers if n <= 1000]
return sum(cleaned_numbers)
\ No newline at end of file
# Testfälle für calculate(), Eingabe: str, Ausgabe: float/int
# 1️⃣ Additionstests
# Eingabe: "1+1" → Erwartete Ausgabe: 2
# Eingabe: "10+20" → Erwartete Ausgabe: 30
# Eingabe: "0+5" → Erwartete Ausgabe: 5
# Eingabe: "-3+7" → Erwartete Ausgabe: 4
# Eingabe: "2.5+2.5" → Erwartete Ausgabe: 5.0
# 2️⃣ Subtraktionstests
# Eingabe: "5-3" → Erwartete Ausgabe: 2
# Eingabe: "10-20" → Erwartete Ausgabe: -10
# Eingabe: "0-5" → Erwartete Ausgabe: -5
# Eingabe: "-3-7" → Erwartete Ausgabe: -10
# Eingabe: "2.5-1.5" → Erwartete Ausgabe: 1.0
# 3️⃣ Multiplikationstests
# Eingabe: "2*3" → Erwartete Ausgabe: 6
# Eingabe: "10*0" → Erwartete Ausgabe: 0
# Eingabe: "-2*5" → Erwartete Ausgabe: -10
# Eingabe: "3.5*2" → Erwartete Ausgabe: 7.0
# Eingabe: "-3*-3" → Erwartete Ausgabe: 9
# 4️⃣ Divisionstests
# Eingabe: "10/2" → Erwartete Ausgabe: 5
# Eingabe: "5/2" → Erwartete Ausgabe: 2.5
# Eingabe: "-6/3" → Erwartete Ausgabe: -2
# Eingabe: "7.5/2.5" → Erwartete Ausgabe: 3.0
# Eingabe: "5/0" → Erwartete Ausgabe: ZeroDivisionError (Fehlermeldung)
# 5️⃣ Komplexe Berechnungen
# Eingabe: "3+5*2" → Erwartete Ausgabe: 13 (Multiplikation vor Addition)
# Eingabe: "(3+5)*2" → Erwartete Ausgabe: 16 (Klammer zuerst)
# Eingabe: "10-4/2" → Erwartete Ausgabe: 8 (Division vor Subtraktion)
# Eingabe: "3+(2*5)-8/4" → Erwartete Ausgabe: 10 (Mehrere Operatoren)
# 6️⃣ Ungültige Eingaben
# Eingabe: "3++5" → Erwartete Ausgabe: SyntaxError (Fehlermeldung)
# Eingabe: "10*/2" → Erwartete Ausgabe: SyntaxError (Fehlermeldung)
# Eingabe: "abc" → Erwartete Ausgabe: ValueError (Fehlermeldung)
import unittest
from src.calculator import Calculator
class TestCalculator(unittest.TestCase):
def setUp(self):
self.calc = Calculator()
# Addition
def test_addition(self):
self.assertEqual(self.calc.calculate("1+1"), 2)
self.assertEqual(self.calc.calculate("10+20"), 30)
self.assertEqual(self.calc.calculate("0+5"), 5)
self.assertEqual(self.calc.calculate("-3+7"), 4)
self.assertEqual(self.calc.calculate("2.5+2.5"), 5.0)
# Subtraktion
def test_subtraction(self):
self.assertEqual(self.calc.calculate("5-3"), 2)
self.assertEqual(self.calc.calculate("10-20"), -10)
self.assertEqual(self.calc.calculate("0-5"), -5)
self.assertEqual(self.calc.calculate("-3-7"), -10)
self.assertEqual(self.calc.calculate("2.5-1.5"), 1.0)
# Multiplikation
def test_multiplication(self):
self.assertEqual(self.calc.calculate("2*3"), 6)
self.assertEqual(self.calc.calculate("10*0"), 0)
self.assertEqual(self.calc.calculate("-2*5"), -10)
self.assertEqual(self.calc.calculate("3.5*2"), 7.0)
self.assertEqual(self.calc.calculate("-3*-3"), 9)
# Division
def test_division(self):
self.assertEqual(self.calc.calculate("10/2"), 5)
self.assertEqual(self.calc.calculate("5/2"), 2.5)
self.assertEqual(self.calc.calculate("-6/3"), -2)
self.assertEqual(self.calc.calculate("7.5/2.5"), 3.0)
# Division durch Null
def test_division_by_zero(self):
with self.assertRaises(ZeroDivisionError):
self.calc.calculate("5/0")
# Komplexe Berechnungen
def test_complex_expressions(self):
self.assertEqual(self.calc.calculate("3+5*2"), 13) # Punkt-vor-Strich beachten
self.assertEqual(self.calc.calculate("(3+5)*2"), 16) # Klammer zuerst
self.assertEqual(self.calc.calculate("10-4/2"), 8) # Division vor Subtraktion
self.assertEqual(self.calc.calculate("3+(2*5)-8/4"), 11.0) # 11
# Ungültige Eingaben
"""def test_invalid_expressions(self):
with self.assertRaises(ValueError):
self.calc.calculate("3++5")
with self.assertRaises(ValueError):
self.calc.calculate("10*/2")
with self.assertRaises(ValueError):
self.calc.calculate("abc")"""
if __name__ == "__main__":
unittest.main()
\ No newline at end of file
import unittest
from src.Count_ED import Counter
class TestCounter(unittest.TestCase):
def setUp(self):
self.c = Counter()
def test_count_ed_regular(self):
self.assertEqual(self.c.count_ed("Decker"), 3)
def test_count_ed_empty(self):
self.assertEqual(self.c.count_ed(""), 0)
def test_count_ed_wo(self):
"""Testet einen String ohne E und D"""
self.assertEqual(self.c.count_ed("Hallo"), 0)
def test_count_ed_case_insensitive(self):
"""Testet verschiedene Groß- und Kleinschreibungen"""
self.assertEqual(self.c.count_ed("Der Esel"), 4)
def test_count_ED_single_letter(self):
"""Testet Eingaben mit nur einem Buchstaben"""
self.assertEqual(self.c.count_ed('D'), 1)
self.assertEqual(self.c.count_ed('E'), 1)
self.assertEqual(self.c.count_ed('d'), 1)
self.assertEqual(self.c.count_ed('e'), 1)
if __name__ == "__main__":
unittest.main()
\ No newline at end of file
# Testfälle roman_to_int, str -> int
# 1. Einzelne römische Ziffern
# Eingabe: "I" → Erwartete Ausgabe: 1
# Eingabe: "V" → Erwartete Ausgabe: 5
# Eingabe: "X" → Erwartete Ausgabe: 10
# Eingabe: "L" → Erwartete Ausgabe: 50
# Eingabe: "C" → Erwartete Ausgabe: 100
# Eingabe: "D" → Erwartete Ausgabe: 500
# Eingabe: "M" → Erwartete Ausgabe: 1000
#2. Mehrere gleiche Ziffern hintereinander (einfache Addition)
# Eingabe: "II" → Erwartete Ausgabe: 2
# Eingabe: "XX" → Erwartete Ausgabe: 20
# Eingabe: "CC" → Erwartete Ausgabe: 200
# Eingabe: "MM" → Erwartete Ausgabe: 2000
#3. Subtraktive Notation
# Eingabe: "IV" → Erwartete Ausgabe: 4
# Eingabe: "IX" → Erwartete Ausgabe: 9
# Eingabe: "XL" → Erwartete Ausgabe: 40
# Eingabe: "XC" → Erwartete Ausgabe: 90
# Eingabe: "CD" → Erwartete Ausgabe: 400
# Eingabe: "CM" → Erwartete Ausgabe: 900
#4. Komplexe Zahlen
# Eingabe: "MCMXCIV" → Erwartete Ausgabe: 1994
#Eingabe: "XIV" → Erwartete Ausgabe: 14
#Eingabe: "CDXLIV" → Erwartete Ausgabe: 444
import unittest
from src.RomanConverter import RomanConverter # Importiere die zu testende Klasse
class TestRomanConverter(unittest.TestCase):
def setUp(self):
self.converter = RomanConverter()
def test_single_digits(self):
self.assertEqual(self.converter.roman_to_int("I"), 1)
self.assertEqual(self.converter.roman_to_int("V"), 5)
self.assertEqual(self.converter.roman_to_int("X"), 10)
def test_multiple_digits(self):
self.assertEqual(self.converter.roman_to_int("II"), 2)
self.assertEqual(self.converter.roman_to_int("XX"), 20)
self.assertEqual(self.converter.roman_to_int("VI"), 6)
def test_subtractive_notation(self):
self.assertEqual(self.converter.roman_to_int("IV"), 4)
self.assertEqual(self.converter.roman_to_int("IX"), 9)
self.assertEqual(self.converter.roman_to_int("XL"), 40)
self.assertEqual(self.converter.roman_to_int("XC"), 90)
def test_complex_numbers(self):
self.assertEqual(self.converter.roman_to_int("MCMXCIV"), 1994)
self.assertEqual(self.converter.roman_to_int("CDXLIV"), 444)
if __name__ == "__main__":
unittest.main()
\ No newline at end of file
# Testfälle add(numbers: str) -> int – StringCalculator
# 1. Leerer String
# Eingabe: "" → Erwartete Ausgabe: 0
# 2. Einzelne Zahl
# Eingabe: "1" → Erwartete Ausgabe: 1
# 3. Zwei Zahlen, getrennt durch Komma
# Eingabe: "1,2" → Erwartete Ausgabe: 3
# 4. Mehr als zwei Zahlen (beliebig viele erlaubt)
# Eingabe: "1,2,3" → Erwartete Ausgabe: 6
# Eingabe: "1,2,3,4,5" → Erwartete Ausgabe: 15
# 5. Leere Einträge ignorieren
# Eingabe: "1,,2" → Erwartete Ausgabe: 3
# Eingabe: "1, ,2" → Erwartete Ausgabe: 3
# Eingabe: ",,1,,2,,," → Erwartete Ausgabe: 3
# 6. Zeilenumbrüche als Trennzeichen erlauben
# Eingabe: "1\n2,3" → Erwartete Ausgabe: 6
# Eingabe: "1,2\n3" → Erwartete Ausgabe: 6
# Eingabe: "1\n2\n3" → Erwartete Ausgabe: 6
# 8. Negative Zahlen → Exception mit allen negativen Werten
# Eingabe: "1,-2" → Exception mit Message "negatives not allowed: -2"
# Eingabe: "-1,-2,3" → Exception mit Message "negatives not allowed: -1, -2"
# 9. Benutzerdefinierter Delimiter über Präfix: "//<delimiter>\n"
# Eingabe: "//;\n1;2" → 3
# Eingabe: "//|\n4|5|6" → 15
# Eingabe: "//_\n7_8_9" → 24
# 10. Zahlen größer als 1000 ignorieren
# Eingabe: "2,1001" → 2
# Eingabe: "1000,1" → 1001 (1000 zählt noch mit)
# Eingabe: "1234,1001,3" → 3
# 11. Delimiter mit beliebiger Länge (Format: //[delimiter]\n)
# Eingabe: "//[***]\n1***2***3" → 6
# Eingabe: "//[abc]\n4abc5abc6" → 15
# Eingabe: "//[+]\n1+2+3" → 6
import unittest
from src.string_calculator import StringCalculator
class TestStringCalculator(unittest.TestCase):
def setUp(self):
# Vor jedem Test wird eine Instanz des Calculators erstellt
self.calc = StringCalculator()
def test_add_empty_string(self):
# Leerer String → 0
self.assertEqual(self.calc.add(""), 0)
def test_add_single_number(self):
# Ein einzelner Wert → int
self.assertEqual(self.calc.add("1"), 1)
def test_add_two_numbers(self):
# Zwei Zahlen → Summe
self.assertEqual(self.calc.add("1,2"), 3)
def test_add_multiple_numbers(self):
# Mehr als zwei Zahlen → Summe
self.assertEqual(self.calc.add("1,2,3"), 6)
self.assertEqual(self.calc.add("1,2,3,4,5"), 15)
def test_add_ignores_empty_entries(self):
# Leere Einträge ignorieren → Summe
self.assertEqual(self.calc.add("1,,2"), 3)
self.assertEqual(self.calc.add("1, ,2"), 3)
self.assertEqual(self.calc.add(",,1,,2,,,"), 3)
def test_add_with_newlines_between_numbers(self):
# Zeilenumbrüche als Trennzeichen erlauben → Summe
self.assertEqual(self.calc.add("1\n2,3"), 6)
self.assertEqual(self.calc.add("1,2\n3"), 6)
self.assertEqual(self.calc.add("1\n2\n3"), 6)
def test_add_raises_exception_on_negative_number(self):
# Negative Zahlen → Exception mit allen negativen Werten
with self.assertRaises(ValueError) as context:
self.calc.add("1,-2")
self.assertIn("negatives not allowed: -2", str(context.exception))
def test_add_raises_exception_on_multiple_negatives(self):
# Negative Zahlen → Exception mit allen negativen Werten
with self.assertRaises(ValueError) as context:
self.calc.add("-1,-2,3")
self.assertIn("negatives not allowed: -1, -2", str(context.exception))
def test_add_with_custom_delimiter(self):
# Benutzerdefinierter Delimiter über Präfix: "//<delimiter>\n"
self.assertEqual(self.calc.add("//;\n1;2"), 3)
self.assertEqual(self.calc.add("//|\n4|5|6"), 15)
self.assertEqual(self.calc.add("//_\n7_8_9"), 24)
def test_add_ignores_numbers_greater_than_1000(self):
# Zahlen größer als 1000 ignorieren
self.assertEqual(self.calc.add("2,1001"), 2)
self.assertEqual(self.calc.add("1000,1"), 1001)
self.assertEqual(self.calc.add("1234,1001,3"), 3)
def test_add_with_multi_char_delimiter(self):
# Delimiter mit beliebiger Länge (Format: //[delimiter]\n)
self.assertEqual(self.calc.add("//[***]\n1***2***3"), 6)
self.assertEqual(self.calc.add("//[abc]\n4abc5abc6"), 15)
self.assertEqual(self.calc.add("//[+]\n1+2+3"), 6)
if __name__ == "__main__":
unittest.main()
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment