SIMPLE = {
    "I": 1,
    "V": 5,
    "X": 10,
    "L": 50,
    "C": 100,
    "D": 500,
    "M": 1000,
}
SIMPLE_REVERSE = {v: k for k, v in SIMPLE.items()}
COMPOUND = {
    "IV": 4,
    "IX": 9,
    "XL": 40,
    "XC": 90,
    "CD": 400,
    "CM": 900,
}
PREFIXES = {k[0] for k in COMPOUND.keys()}
COMPOUND_REVERSE = {v: k for k, v in COMPOUND.items()}
ALL = SIMPLE | COMPOUND
ALL_REVERSE = {v: k for k, v in ALL.items()}


def i2r(i: int) -> str:
    if i > 100_000:
        raise ValueError(f"{i} is too silly")

    r: list[str] = []

    for int_val, roman_val in sorted(ALL_REVERSE.items(), reverse=True):
        remainder = i % int_val

        r += [roman_val] * int((i - remainder) / int_val)

        i = remainder

    return "".join(r)


def r2i(r: str) -> int:
    total = 0
    offset = 0

    for i in range(len(r)):
        if i + offset > len(r) - 1:
            break

        c = r[i + offset]
        if c in PREFIXES and (i + offset + 1) < len(r) and c + r[i + offset + 1] in ALL:
            total += ALL[c + r[i + offset + 1]]
            offset += 1
            continue

        total += ALL[c]

    return total
