Калькулятор римских цифр с "для меня в X"

Я пытался создать калькулятор, который легко конвертирует римские в числительные. Может кто-нибудь сказать мне, как выбрать слова из двух символов, чтобы иметь высокий приоритет?

** Роман это строка

#Roman Numeral calculator

def RomanToDecimal(roman):
DecimalValue=0
for i in roman:
    if i == "CM":
        DecimalValue += 900
    if i == "IV":
        DecimalValue += 4
    if i == "IX":
        DecimalValue += 9
    if i == "XL":
        DecimalValue += 40
    if i == "XC":
        DecimalValue += 90
    if i == "CD":
        DecimalValue += 400
    elif i in roman:
        if i == "I":
            DecimalValue += 1
        if i == "V":
            DecimalValue += 5
        if i == "X":
            DecimalValue += 10
        if i == "L":
            DecimalValue += 50
        if i == "C":
            DecimalValue += 100
        if i == "D":
            DecimalValue += 500
        if i == "M":
            DecimalValue += 1000

return DecimalValue

и я новичок здесь, поэтому, пожалуйста, попробуйте ответить мне с терпением

3 ответа

Решение

Хотя есть более эффективные способы сделать это, это следует стилю вашего собственного кода, так что, надеюсь, будет легче следовать.

Основным изменением является замена for петля с while петля и ручной счетчик. Это позволяет пропустить два шага, когда мы сталкиваемся с одним из наших двойных символов. Затем мы извлекаем персонажей и осматриваем их - сначала заглядываем в два символа вперед, затем по отдельности. Если мы находим совпадение длиной 2 символа, мы делаем шаг 2 (мимо них) и перезапускаем цикл:

def RomanToDecimal(roman):
    DecimalValue=0 
    i = 0 # Position in string

    while i < len(roman):

        # Test for 2 char first    
        if i < len(roman)-1: # Make sure we're not on the last letter
            # Get current + next letters
            s = roman[i:i+2] 
            add = False

            if s == "CM":
                add = 900
            elif s == "IV":
                add = 4
            elif s == "IX":
                add = 9
            elif s == "XL":
                add = 40
            elif s == "XC":
                add = 90
            elif s == "CD":
                add = 400

            if add: # We've found a match
                i += 2 # Step 2
                DecimalValue += add # Add the value
                continue # Next loop

        # If we get here the 2 character match failed
        # Single char match
        s = roman[i] 

        if s == "I":
            DecimalValue += 1
        elif s == "V":
            DecimalValue += 5
        elif s == "X":
            DecimalValue += 10
        elif s == "L":
            DecimalValue += 50
        elif s == "C":
            DecimalValue += 100
        elif s == "D":
            DecimalValue += 500
        elif s == "M":
            DecimalValue += 1000

        i += 1

    return DecimalValue

RomanToDecimal('XIXIX')
28

Следует отметить, что приведенное выше не является действительной строкой римских цифр (28 правильно представлено XXVIII), но, надеюсь, это не проблема!

Дайте мне знать, если код где-то неясен, и я добавлю больше комментариев.

Я бы рекомендовал сначала перевести римский на арабский язык один за другим, умножить некоторые из них на -1 и, наконец, просто сложить:

roman = 'MMXIV'
D = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
tmp = [D[x] for x in roman]
for i in range(len(tmp) - 1):
    if tmp[i + 1] > tmp[i]:
        tmp[i] *= -1
print(sum(tmp))

У классических вопросов есть классические ответы в Rosetta Code: http://rosettacode.org/wiki/Roman_numerals/Decode

_rdecode = dict(zip('MDCLXVI', (1000, 500, 100, 50, 10, 5, 1)))

def decode( roman ):
    result = 0
    for r, r1 in zip(roman, roman[1:]):
        rd, rd1 = _rdecode[r], _rdecode[r1]
        result += -rd if rd < rd1 else rd
    return result + _rdecode[roman[-1]]

if __name__ == '__main__':
    for r in 'MCMXC MMVIII MDCLXVI'.split():
        print( r, decode(r) )
Другие вопросы по тегам