# Roman Numerals Helper
# https://www.codewars.com/kata/51b66044bce5799a7f000003/train/python
class RomanNumerals:
# @staticmethod 是一个装饰器, 用来标识一个方法为静态方法
# 静态方法不需要实例化, 可以直接通过类名调用
# 静态方法不能访问实例属性, 只能访问类属性, 因此不能使用self
@staticmethod
def to_roman(val : int) -> str:
# val : int 是参数类型提示, 表示val是一个整数
# -> str 是返回值类型提示, 表示返回一个字符串
roman_numerals = [
(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 (num,roman) in roman_numerals:
while val >= num:
result += roman
val-=num
return result
@staticmethod
def from_roman(roman_num : str) -> int:
# roman_to_int = {
# 'M': 1000, 'CM': 900, 'D': 500, 'CD': 400, # D : +500, M : +1000, C : -100
# 'C': 100, 'XC': 90, 'L': 50, 'XL': 40, # L : +40, C : +100, X : -10
# 'X': 10, 'IX': 9, 'V': 5, 'IV': 4, # V : +5, X : +10, I : -1
# 'I': 1 # I : +1
# # I, V, X, L, C, D, M
# # 1, 5, 10, 50, 100, 500, 1000
# }
result = 0
max = 0
char_value = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
# 字符串切片语法: [start:stop:step],其中start是开始的索引,stop是结束的索引,step是步长
# 如果start和stop都没有指定,则默认从头到尾,step默认为1
# 如果step为负数,则从右向左提取元素,默认的起始索引是-1,默认的结束索引是-len(roman_num)-1
# roman_num[::-1]表示从末尾字符开始,每次向前取一个字符,直到第一个字符,包括第一个字符,即字符串反转
# map(function, iterable)函数,将function应用于iterable的每个元素,返回一个迭代器
for curr in map(lambda ch : {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}[ch],roman_num[::-1]):
if curr >= max:
max = curr
result += curr
else:
result -= curr
return result
# 测试
# for i in range(1, 40):
# print(RomanNumerals.to_roman(i))
print(RomanNumerals.from_roman('MCDXI'))