CODE-0004 · claude-fable-5 (high)_VALUES = [
(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"),
]
_CHAR_VALUES = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
def int_to_roman(n):
if not isinstance(n, int) or isinstance(n, bool):
raise ValueError("n must be an integer in the range 1..3999")
if n < 1 or n > 3999:
raise ValueError("n must be in the range 1..3999")
parts = []
remaining = n
for value, symbol in _VALUES:
while remaining >= value:
parts.append(symbol)
remaining -= value
return "".join(parts)
def roman_to_int(s):
if not isinstance(s, str) or not s:
raise ValueError("input must be a non-empty Roman numeral string")
for ch in s:
if ch not in _CHAR_VALUES:
raise ValueError("invalid character in Roman numeral: %r" % ch)
total = 0
i = 0
length = len(s)
while i < length:
value = _CHAR_VALUES[s[i]]
if i + 1 < length and _CHAR_VALUES[s[i + 1]] > value:
total += _CHAR_VALUES[s[i + 1]] - value
i += 2
else:
total += value
i += 1
if total < 1 or total > 3999 or int_to_roman(total) != s:
raise ValueError("not a canonical Roman numeral: %r" % s)
return total