Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/roman_converter/zaccagnino_from_roman.py
Original file line number Diff line number Diff line change
@@ -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)
62 changes: 62 additions & 0 deletions src/roman_converter/zaccagnino_to_roman.py
Original file line number Diff line number Diff line change
@@ -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]
)








22 changes: 22 additions & 0 deletions tests/roman_converter/zaccagnino/tests_zaccagnino_from_roman.py
Original file line number Diff line number Diff line change
@@ -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
23 changes: 23 additions & 0 deletions tests/roman_converter/zaccagnino/tests_zaccagnino_to_roman.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from types import ModuleType


def test_to_roman1(impl: ModuleType):
assert impl.to_roman1(1) == "I"
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(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(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"