Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
804 views
in Technique[技术] by (71.8m points)

python - Check if an input is a valid roman numeral

I got a program that converts Roman numerals to integers and vice versa. My problem is that I don′t really know how to create a function that checks if the user input is a valid roman numeral. My code right now:

def checkIfRomanNumeral(numeral):
"""Controls that the userinput only contains valid roman numerals"""
    numeral = numeral.upper()
    validRomanNumerals = ["M", "D", "C", "L", "X", "V", "I", "(", ")"]
    for letters in numeral:
        if letters not in validRomanNumerals:
            print("Sorry that is not a valid roman numeral")
            return True
        elif letters in validRomanNumerals:
            romanToInt(numeral)
            break

I think the problem right now is that the function only checks the first letter in the input(numeral) because of the for loop. Could someone help me to make the function check the whole input and print("Sorry that is not a valid Roman numeral") if any letter of the input is not a Roman numeral. The parenthesis in the list validRomanNumerals are used to convert numbers bigger than 4000 so they must be there.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Writing a converter from ints to Romans is a standard interview question. I once wrote the following bi-directional implementation (toString-- decimal to Roman; parse -- Roman to decimal). The implementaion saticifies a number of additional criteria on the representation of Roman numbers, which are not obligatory, but generally followed:

'''
Created on Feb 7, 2013

@author: olegs
'''

ROMAN_CONSTANTS = (
            ( "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" ),
            ( "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" ),
            ( "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" ),
            ( "", "M", "MM", "MMM", "",   "",  "-",  "",    "",     ""   ),
        )

ROMAN_SYMBOL_MAP = dict(I=1, V=5, X=10, L=50, C=100, D=500, M=1000)

CUTOFF = 4000
BIG_DEC = 2900
BIG_ROMAN = "MMCM"
ROMAN_NOUGHT = "nulla"

def digits(num):
    if num < 0:
        raise Exception('range error: negative numbers not supported')
    if num % 1 != 0.0:
        raise Exception('floating point numbers not supported')
    res = []
    while num > 0:
        res.append(num % 10)
        num //= 10
    return res

def toString(num, emptyZero=False):
    if num < CUTOFF:
        digitlist = digits(num)
        if digitlist:
            res = reversed([ ROMAN_CONSTANTS[order][digit] for order, digit in enumerate(digitlist) ])
            return "".join(res)
        else:
            return "" if emptyZero else ROMAN_NOUGHT 
    else:
        if num % 1 != 0.0:
            raise Exception('floating point numbers not supported')
        # For numbers over or equal the CUTOFF, the remainder of division by 2900
        # is represented as above, prepended with the multiples of MMCM (2900 in Roman),
        # which guarantees no more than 3 repetitive Ms.
        return BIG_ROMAN * (num // BIG_DEC) + toString(num % BIG_DEC, emptyZero=True)

def parse(numeral):
    numeral = numeral.upper()
    result = 0
    if numeral == ROMAN_NOUGHT.upper():
        return result
    lastVal = 0
    lastCount = 0
    subtraction = False
    for symbol in numeral[::-1]:
        value = ROMAN_SYMBOL_MAP.get(symbol)
        if not value:
            raise Exception('incorrect symbol')
        if lastVal == 0:
            lastCount = 1
            lastVal = value
        elif lastVal == value:
            lastCount += 1
            # exceptions
        else:
            result += (-1 if subtraction else 1) * lastVal * lastCount
            subtraction = lastVal > value
            lastCount = 1
            lastVal = value
    return result + (-1 if subtraction else 1) * lastVal * lastCount

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.8k users

...