From 2d15e92c0c5b96a1650080bd15aaa064fdf49d57 Mon Sep 17 00:00:00 2001 From: Shaina Date: Sat, 21 Feb 2026 11:17:38 -0500 Subject: [PATCH 1/3] added the to_roman implementations --- src/roman_converter/zaccagnino.py | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/roman_converter/zaccagnino.py diff --git a/src/roman_converter/zaccagnino.py b/src/roman_converter/zaccagnino.py new file mode 100644 index 0000000..830fedd --- /dev/null +++ b/src/roman_converter/zaccagnino.py @@ -0,0 +1,62 @@ +def to_roman1(arabic: int) -> str: + if not 0 < arabic < 4000: + return "Input must be between 1 and 3999" + + roman_mapping = [ + (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 roman_mapping: + count = arabic // value + result += numeral * count + arabic %= value + + return result + +def arabic_to_roman_greedy(n: int) -> str: + """Greedy mapping implementation. Supports 1..3999.""" + if not isinstance(n, int): + raise TypeError("n must be int") + if n <= 0 or n >= 4000: + raise ValueError("n must be between 1 and 3999") + vals = [ + (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"), + ] + res = [] + for val, sym in vals: + count, n = divmod(n, val) + res.append(sym * count) + if n == 0: + break + return "".join(res) + + +def arabic_to_roman_table(n: int) -> str: + """Table-driven implementation using digit breakdown. Supports 1..3999.""" + if not isinstance(n, int): + raise TypeError("n must be int") + if n <= 0 or n >= 4000: + raise ValueError("n must be between 1 and 3999") + thousands = ["", "M", "MM", "MMM"] + hundreds = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"] + tens = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"] + ones = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"] + return ( + thousands[(n // 1000) % 10] + + hundreds[(n // 100) % 10] + + tens[(n // 10) % 10] + + ones[n % 10] + ) + + + + + + + + From 96e03a8325078fd9d2cc248be3001b41dda5f426 Mon Sep 17 00:00:00 2001 From: Shaina Date: Mon, 2 Mar 2026 17:07:15 -0500 Subject: [PATCH 2/3] adding test suite --- tests/roman_converter/tests_zaccagnino.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/roman_converter/tests_zaccagnino.py diff --git a/tests/roman_converter/tests_zaccagnino.py b/tests/roman_converter/tests_zaccagnino.py new file mode 100644 index 0000000..73ff7d1 --- /dev/null +++ b/tests/roman_converter/tests_zaccagnino.py @@ -0,0 +1,23 @@ +from types import ModuleType + + +def test_to_roman1(impl: ModuleType): + assert impl.to_roman1(1) == "I" + assert impl.to_roman1(50) == "L" + assert impl.to_roman1(100) == "C" + assert impl.to_roman1(1000) == "M" + assert impl.to_roman1(3999) == "MMMCMXCIX" + +def test_arabic_to_roman_greedy(impl: ModuleType): + assert impl.arabic_to_roman_greedy(1) == "I" + assert impl.arabic_to_roman_greedy(50) == "L" + assert impl.arabic_to_roman_greedy(100) == "C" + assert impl.arabic_to_roman_greedy(1000) == "M" + assert impl.arabic_to_roman_greedy(3999) == "MMMCMXCIX" + +def test_arabic_to_roman_table(impl: ModuleType): + assert impl.arabic_to_roman_table(1) == "I" + assert impl.arabic_to_roman_table(50) == "L" + assert impl.arabic_to_roman_table(100) == "C" + assert impl.arabic_to_roman_table(1000) == "M" + assert impl.arabic_to_roman_table(3999) == "MMMCMXCIX" \ No newline at end of file From aae263625e6f91f272db19dba9a81801107ce30c Mon Sep 17 00:00:00 2001 From: Shaina Date: Mon, 2 Mar 2026 18:21:56 -0500 Subject: [PATCH 3/3] adding in other tests --- src/roman_converter/zaccagnino_from_roman.py | 28 +++++++++++++++++++ .../{zaccagnino.py => zaccagnino_to_roman.py} | 0 .../zaccagnino/tests_zaccagnino_from_roman.py | 22 +++++++++++++++ .../tests_zaccagnino_to_roman.py} | 18 ++++++------ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 src/roman_converter/zaccagnino_from_roman.py rename src/roman_converter/{zaccagnino.py => zaccagnino_to_roman.py} (100%) create mode 100644 tests/roman_converter/zaccagnino/tests_zaccagnino_from_roman.py rename tests/roman_converter/{tests_zaccagnino.py => zaccagnino/tests_zaccagnino_to_roman.py} (50%) diff --git a/src/roman_converter/zaccagnino_from_roman.py b/src/roman_converter/zaccagnino_from_roman.py new file mode 100644 index 0000000..3a4e223 --- /dev/null +++ b/src/roman_converter/zaccagnino_from_roman.py @@ -0,0 +1,28 @@ +def roman_to_int_comparison(s: str) -> int: + roman_map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} + num = 0 + for i in range(len(s)): + if i + 1 < len(s) and roman_map[s[i]] < roman_map[s[i+1]]: + num -= roman_map[s[i]] + else: + num += roman_map[s[i]] + return num + +def romanToInt_reverse(s: str) -> int: + roman_map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} + integer, previous_value = 0, 0 + for ch in reversed(s): + current_value = roman_map[ch] + if current_value < previous_value: + integer -= current_value + else: + integer += current_value + previous_value = current_value + return integer + +def romanToInt_replace(s: str) -> int: + roman_map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} + s = s.replace("IV", "IIII").replace("IX", "VIIII") + s = s.replace("XL", "XXXX").replace("XC", "LXXXX") + s = s.replace("CD", "CCCC").replace("CM", "DCCCC") + return sum(roman_map[x] for x in s) diff --git a/src/roman_converter/zaccagnino.py b/src/roman_converter/zaccagnino_to_roman.py similarity index 100% rename from src/roman_converter/zaccagnino.py rename to src/roman_converter/zaccagnino_to_roman.py diff --git a/tests/roman_converter/zaccagnino/tests_zaccagnino_from_roman.py b/tests/roman_converter/zaccagnino/tests_zaccagnino_from_roman.py new file mode 100644 index 0000000..9fc9938 --- /dev/null +++ b/tests/roman_converter/zaccagnino/tests_zaccagnino_from_roman.py @@ -0,0 +1,22 @@ +from types import ModuleType + +def test_roman_to_int_comparison(impl: ModuleType): + assert impl.roman_to_int_comparison("I") == 1 + assert impl.roman_to_int_comparison("IV") == 4 + assert impl.roman_to_int_comparison("XXVI") == 26 + assert impl.roman_to_int_comparison("MDCLXVI") == 1666 + assert impl.roman_to_int_comparison("MMMCMXCIX") == 3999 + +def romanToInt_reverse(impl: ModuleType): + assert impl.romanToInt_reverse("I") == 1 + assert impl.romanToInt_reverse("IV") == 4 + assert impl.romanToInt_reverse("XXVI") == 26 + assert impl.romanToInt_reverse("MDCLXVI") == 1666 + assert impl.romanToInt_reverse("MMMCMXCIX") == 3999 + +def test_romanToInt_replace(impl: ModuleType): + assert impl.romanToInt_replace("I") == 1 + assert impl.romanToInt_replace("IV") == 4 + assert impl.romanToInt_replace("XXVI") == 26 + assert impl.romanToInt_replace("MDCLXVI") == 1666 + assert impl.romanToInt_replace("MMMCMXCIX") == 3999 \ No newline at end of file diff --git a/tests/roman_converter/tests_zaccagnino.py b/tests/roman_converter/zaccagnino/tests_zaccagnino_to_roman.py similarity index 50% rename from tests/roman_converter/tests_zaccagnino.py rename to tests/roman_converter/zaccagnino/tests_zaccagnino_to_roman.py index 73ff7d1..dbc700a 100644 --- a/tests/roman_converter/tests_zaccagnino.py +++ b/tests/roman_converter/zaccagnino/tests_zaccagnino_to_roman.py @@ -3,21 +3,21 @@ def test_to_roman1(impl: ModuleType): assert impl.to_roman1(1) == "I" - assert impl.to_roman1(50) == "L" - assert impl.to_roman1(100) == "C" - assert impl.to_roman1(1000) == "M" + assert impl.to_roman1(52) == "LII" + assert impl.to_roman1(176) == "CLXXVI" + assert impl.to_roman1(1256) == "MCCLVI" assert impl.to_roman1(3999) == "MMMCMXCIX" def test_arabic_to_roman_greedy(impl: ModuleType): assert impl.arabic_to_roman_greedy(1) == "I" - assert impl.arabic_to_roman_greedy(50) == "L" - assert impl.arabic_to_roman_greedy(100) == "C" - assert impl.arabic_to_roman_greedy(1000) == "M" + assert impl.arabic_to_roman_greedy(52) == "LII" + assert impl.arabic_to_roman_greedy(176) == "CLXXVI" + assert impl.arabic_to_roman_greedy(1256) == "MCCLVI" assert impl.arabic_to_roman_greedy(3999) == "MMMCMXCIX" def test_arabic_to_roman_table(impl: ModuleType): assert impl.arabic_to_roman_table(1) == "I" - assert impl.arabic_to_roman_table(50) == "L" - assert impl.arabic_to_roman_table(100) == "C" - assert impl.arabic_to_roman_table(1000) == "M" + assert impl.arabic_to_roman_table(52) == "LII" + assert impl.arabic_to_roman_table(176) == "CLXXVI" + assert impl.arabic_to_roman_table(1256) == "MCCLVI" assert impl.arabic_to_roman_table(3999) == "MMMCMXCIX" \ No newline at end of file