diff --git a/src/interfaces.py b/src/interfaces.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fc645736ebe7edf2091db66c3738825f50fd923f 100644 --- a/src/interfaces.py +++ b/src/interfaces.py @@ -0,0 +1,6 @@ +from abc import ABC, abstractmethod + +class IRomanNumerals(ABC): + @abstractmethod + def to_roman(self, num): + pass \ No newline at end of file diff --git a/src/romannumerals.py b/src/romannumerals.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3f3eaf1e8e956ca023c64ae71e38caefb1198940 100644 --- a/src/romannumerals.py +++ b/src/romannumerals.py @@ -0,0 +1,23 @@ +from src.interfaces import IRomanNumerals + + +class RomanNumerals(IRomanNumerals): + def to_roman(self, num): + if not isinstance(num, int): + raise ValueError("Eingabe muss eine ganze Zahl sein") + if num <= 0 or num >= 4000: + raise ValueError("Zahl muss zwischen 1 und 3999 liegen") + + val = [ + (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), + (100, "C"), (90, "XC"), (50, "L"), (40, "XL"), + (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), + (1, "I") + ] + + result = "" + for (value, numeral) in val: + while num >= value: + result += numeral + num -= value + return result \ No newline at end of file diff --git a/tests/test_romannumerals.py b/tests/test_romannumerals.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9a774cc92787102f3ef685b0c6a80138e5bbcedf 100644 --- a/tests/test_romannumerals.py +++ b/tests/test_romannumerals.py @@ -0,0 +1,108 @@ +# Basisfälle +# Bei Eingabe der Zahl 1, erhalte ich das Ergebnis I +# Bei Eingabe der Zahl 5, erhalte ich das Ergebnis V +# Bei Eingabe der Zahl 10, erhalte ich das Ergebnis X +# Bei Eingabe der Zahl 50, erhalte ich das Ergebnis L +# Bei Eingabe der Zahl 100, erhalte ich das Ergebnis C +# Bei Eingabe der Zahl 500, erhalte ich das Ergebnis D +# Bei Eingabe der Zahl 1000, erhalte ich das Ergebnis M +# Substraktionsregel +# Bei Eingabe der Zahl 4, erhalte ich das Ergebnis IV +# Bei Eingabe der Zahl 9, erhalte ich das Ergebnis IX +# Bei Eingabe der Zahl 40, erhalte ich das Ergebnis XL +# Bei Eingabe der Zahl 90, erhalte ich das Ergebnis XC +# Bei Eingabe der Zahl 400, erhalte ich das Ergebnis CD +# Bei Eingabe der Zahl 900, erhalte ich das Ergebnis CM +# Additionsregel +# Bei Eingabe der Zahl 2 erhalte ich das Ergebnis "II" +# Bei Eingabe der Zahl 3 erhalte ich das Ergebnis "III" +# Bei Eingabe der Zahl 6 erhalte ich das Ergebnis "VI" +# Bei Eingabe der Zahl 8 erhalte ich das Ergebnis "VIII" +# Bei Eingabe der Zahl 30 erhalte ich das Ergebnis "XXX" +# Bei Eingabe der Zahl 80 erhalte ich das Ergebnis "LXXX" +# Kombination aus Addition und Subtraktion +# Bei Eingabe der Zahl 14 erhalte ich das Ergebnis "XIV" +# Bei Eingabe der Zahl 19 erhalte ich das Ergebnis "XIX" +# Bei Eingabe der Zahl 29 erhalte ich das Ergebnis "XXIX" +# Bei Eingabe der Zahl 44 erhalte ich das Ergebnis "XLIV" +# Bei Eingabe der Zahl 99 erhalte ich das Ergebnis "XCIX" +# Bei Eingabe der Zahl 444 erhalte ich das Ergebnis "CDXLIV" +# Bei Eingabe der Zahl 999 erhalte ich das Ergebnis "CMXCIX" +# Größere Zahlen +# Bei Eingabe der Zahl 1001 erhalte ich das Ergebnis "MI" +# Bei Eingabe der Zahl 1987 erhalte ich das Ergebnis "MCMLXXXVII" +# Bei Eingabe der Zahl 2023 erhalte ich das Ergebnis "MMXXIII" +# Bei Eingabe der Zahl 3999 erhalte ich das Ergebnis "MMMCMXCIX" +# Fehlerfälle +# Bei Eingabe der Zahl 0 erhalte ich eine Fehlermeldung +# Bei Eingabe der Zahl -1 erhalte ich eine Fehlermeldung +# Bei Eingabe der Zahl 4000 erhalte ich eine Fehlermeldung +# Bei Eingabe der Zeichenfolge "ABC" erhalte ich eine Fehlermeldung +# Bei Eingabe von None erhalte ich eine Fehlermeldung +# Bei Eingabe der Zahl 3.14 erhalte ich eine Fehlermeldung + +import unittest +from src.romannumerals import RomanNumerals + + +class TestRomanNumerals(unittest.TestCase): + def setUp(self): + self.converter = RomanNumerals() + + def test_to_roman_basic(self): + self.assertEqual(self.converter.to_roman(1), "I") + self.assertEqual(self.converter.to_roman(5), "V") + self.assertEqual(self.converter.to_roman(10), "X") + self.assertEqual(self.converter.to_roman(50), "L") + self.assertEqual(self.converter.to_roman(100), "C") + self.assertEqual(self.converter.to_roman(500), "D") + self.assertEqual(self.converter.to_roman(1000), "M") + + def test_to_roman_subtraction(self): + self.assertEqual(self.converter.to_roman(4), "IV") + self.assertEqual(self.converter.to_roman(9), "IX") + self.assertEqual(self.converter.to_roman(40), "XL") + self.assertEqual(self.converter.to_roman(90), "XC") + self.assertEqual(self.converter.to_roman(400), "CD") + self.assertEqual(self.converter.to_roman(900), "CM") + + def test_to_roman_addition(self): + self.assertEqual(self.converter.to_roman(2), "II") + self.assertEqual(self.converter.to_roman(3), "III") + self.assertEqual(self.converter.to_roman(6), "VI") + self.assertEqual(self.converter.to_roman(8), "VIII") + self.assertEqual(self.converter.to_roman(30), "XXX") + self.assertEqual(self.converter.to_roman(80), "LXXX") + + def test_to_roman_mixed(self): + self.assertEqual(self.converter.to_roman(14), "XIV") + self.assertEqual(self.converter.to_roman(19), "XIX") + self.assertEqual(self.converter.to_roman(29), "XXIX") + self.assertEqual(self.converter.to_roman(44), "XLIV") + self.assertEqual(self.converter.to_roman(99), "XCIX") + self.assertEqual(self.converter.to_roman(444), "CDXLIV") + self.assertEqual(self.converter.to_roman(999), "CMXCIX") + + def test_to_roman_large_numbers(self): + self.assertEqual(self.converter.to_roman(1001), "MI") + self.assertEqual(self.converter.to_roman(1987), "MCMLXXXVII") + self.assertEqual(self.converter.to_roman(2023), "MMXXIII") + self.assertEqual(self.converter.to_roman(3999), "MMMCMXCIX") + + def test_to_roman_invalid(self): + with self.assertRaises(ValueError): + self.converter.to_roman(0) + with self.assertRaises(ValueError): + self.converter.to_roman(-1) + with self.assertRaises(ValueError): + self.converter.to_roman(4000) + with self.assertRaises(ValueError): + self.converter.to_roman("ABC") + with self.assertRaises(ValueError): + self.converter.to_roman(None) + with self.assertRaises(ValueError): + self.converter.to_roman(3.14) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file