|
1 | 1 | ROMAN = [
|
2 |
| - (1000, "M"), |
3 |
| - (900, "CM"), |
4 |
| - (500, "D"), |
5 |
| - (400, "CD"), |
6 |
| - (100, "C"), |
7 |
| - (90, "XC"), |
8 |
| - (50, "L"), |
9 |
| - (40, "XL"), |
10 |
| - (10, "X"), |
11 |
| - (9, "IX"), |
12 |
| - (5, "V"), |
13 |
| - (4, "IV"), |
14 |
| - (1, "I"), |
| 2 | + (1000000, "M_"), (900000, "C_M_"), (500000, "D_"), (400000, "C_D_"), |
| 3 | + (100000, "C_"), (90000, "X_C_"), (50000, "L_"), (40000, "X_L_"), |
| 4 | + (10000, "X_"), (9000, "I_X_"), (5000, "V_"), (4000, "I_V_"), |
| 5 | + (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), |
| 6 | + (100, "C"), (90, "XC"), (50, "L"), (40, "XL"), |
| 7 | + (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I") |
15 | 8 | ]
|
16 |
| - |
17 |
| - |
18 | 9 | def roman_to_int(roman: str) -> int:
|
19 | 10 | """
|
20 |
| - LeetCode No. 13 Roman to Integer |
21 |
| - Given a roman numeral, convert it to an integer. |
22 |
| - Input is guaranteed to be within the range from 1 to 3999. |
23 |
| - https://en.wikipedia.org/wiki/Roman_numerals |
24 |
| - >>> tests = {"III": 3, "CLIV": 154, "MIX": 1009, "MMD": 2500, "MMMCMXCIX": 3999} |
| 11 | + Convert a Roman numeral to an integer, supporting Vinculum notation (underscore _ represents 1000 times). |
| 12 | + LeetCode No. 13 Roman to Integer |
| 13 | + Given a roman numeral, convert it to an integer. |
| 14 | + Input is guaranteed to be within the range from 1 to 3999. |
| 15 | + https://en.wikipedia.org/wiki/Roman_numerals |
| 16 | + >>> all(roman_to_int(key) == value for key, value in tests.items()) |
| 17 | + >>> tests = {"III": 3, "CLIV": 154, "MIX": 1009, "MMD": 2500, "MMMCMXCIX": 3999, "I_V_": 4000, "X_": 10000, "M_": 1000000} |
25 | 18 | >>> all(roman_to_int(key) == value for key, value in tests.items())
|
26 | 19 | True
|
27 | 20 | """
|
28 |
| - vals = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000} |
29 |
| - total = 0 |
30 |
| - place = 0 |
31 |
| - while place < len(roman): |
32 |
| - if (place + 1 < len(roman)) and (vals[roman[place]] < vals[roman[place + 1]]): |
33 |
| - total += vals[roman[place + 1]] - vals[roman[place]] |
34 |
| - place += 2 |
| 21 | + vals = { |
| 22 | + "I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000, |
| 23 | + "I_": 1000, "V_": 5000, "X_": 10000, "L_": 50000, "C_": 100000, "D_": 500000, "M_": 1000000 |
| 24 | + } |
| 25 | + i, total = 0, 0 |
| 26 | + while i < len(roman): |
| 27 | + if i + 1 < len(roman) and (roman[i:i+2] in vals): # 处理 `_` 记法 |
| 28 | + total += vals[roman[i:i+2]] |
| 29 | + i += 2 |
35 | 30 | else:
|
36 |
| - total += vals[roman[place]] |
37 |
| - place += 1 |
| 31 | + total += vals[roman[i]] |
| 32 | + i += 1 |
38 | 33 | return total
|
39 |
| - |
40 |
| - |
41 |
| -def int_to_roman(number: int) -> str: |
| 34 | + def int_to_roman(number: int) -> str: |
42 | 35 | """
|
43 |
| - Given a integer, convert it to an roman numeral. |
44 |
| - https://en.wikipedia.org/wiki/Roman_numerals |
45 |
| - >>> tests = {"III": 3, "CLIV": 154, "MIX": 1009, "MMD": 2500, "MMMCMXCIX": 3999} |
| 36 | + Convert an integer to a Roman numeral, supporting Vinculum notation (underscore _ represents 1000 times). |
| 37 | + Given a integer, convert it to an roman numeral. |
| 38 | + https://en.wikipedia.org/wiki/Roman_numerals |
| 39 | + >>> tests = {"III": 3, "CLIV": 154, "MIX": 1009, "MMD": 2500, "MMMCMXCIX": 3999, "I_V_": 4000, "X_": 10000, "M_": 1000000} |
46 | 40 | >>> all(int_to_roman(value) == key for key, value in tests.items())
|
47 | 41 | True
|
48 | 42 | """
|
| 43 | + if not isinstance(number, int) or number < 1: |
| 44 | + raise ValueError("Input must be a positive integer greater than 0") |
| 45 | + |
49 | 46 | result = []
|
50 | 47 | for arabic, roman in ROMAN:
|
51 |
| - (factor, number) = divmod(number, arabic) |
| 48 | + factor, number = divmod(number, arabic) |
52 | 49 | result.append(roman * factor)
|
53 | 50 | if number == 0:
|
54 |
| - break |
| 51 | + reak |
55 | 52 | return "".join(result)
|
56 | 53 |
|
57 |
| - |
58 | 54 | if __name__ == "__main__":
|
59 | 55 | import doctest
|
60 |
| - |
61 | 56 | doctest.testmod()
|
0 commit comments