CODE-0004 · grok-4.20-reasoning (default)
def int_to_roman(n):
    if not isinstance(n, int):
        raise ValueError("n must be an integer")
    if n < 1 or n > 3999:
        raise ValueError("n must be between 1 and 3999")
    vals = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
    syms = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
    roman = ""
    i = 0
    while n > 0:
        for _ in range(n // vals[i]):
            roman += syms[i]
            n -= vals[i]
        i += 1
    return roman


def roman_to_int(s):
    if not isinstance(s, str):
        raise ValueError("invalid roman numeral")
    if not s:
        raise ValueError("empty string")
    roman_values = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
    if any(c not in roman_values for c in s):
        raise ValueError("invalid roman numeral")
    total = 0
    prev_value = 0
    for char in reversed(s):
        value = roman_values[char]
        if value < prev_value:
            total -= value
        else:
            total += value
        prev_value = value
    if total < 1 or total > 3999:
        raise ValueError("roman numeral out of range")
    if int_to_roman(total) != s:
        raise ValueError("non-canonical roman numeral")
    return total