Basic program to convert integer to Roman numerals?

后端 未结 24 1095
孤独总比滥情好
孤独总比滥情好 2020-11-30 11:52

I\'m trying to write a code that converts a user-inputted integer into its Roman numeral equivalent. What I have so far is:

The point of the generate_

相关标签:
24条回答
  • 2020-11-30 12:35

    This is my recursive function approach to convert a number to its roman equivalent

        def solution(n):
            # TODO convert int to roman string
            string=''
            symbol=['M','D','C','L','X','V','I']
            value = [1000,500,100,50,10,5,1]
            num = 10**(len(str(n))-1)
            quo = n//num
            rem=n%num
            if quo in [0,1,2,3]:
                string=string+symbol[value.index(num)]*quo
            elif quo in [4,5,6,7,8]:
                tem_str=symbol[value.index(num)]+symbol[value.index(num)-1]
                        +symbol[value.index(num)]*3
                string=string+tem_str[(min(quo,5)-4):(max(quo,5)-3)]
            else:
                string=string+symbol[value.index(num)]+symbol[value.index(num)-2]
            if rem==0:
                return string
            else:
                string=string+solution(rem)
            return string
    
    print(solution(499))
    print(solution(999))
    print(solution(2456))
    print(solution(2791))
    CDXCIX
    CMXCIX
    MMCDLVI
    MMDCCXCI
    
    0 讨论(0)
  • 2020-11-30 12:36

    I was working through this conversion as a kata exercise, and I came up with a solution that takes advantage of Python's string operations:

    from collections import namedtuple
    
    Abbreviation = namedtuple('Abbreviation', 'long short')
    abbreviations = [
        Abbreviation('I' * 1000, 'M'),
        Abbreviation('I' * 500, 'D'),
        Abbreviation('I' * 100, 'C'),
        Abbreviation('I' * 50, 'L'),
        Abbreviation('I' * 10, 'X'),
        Abbreviation('I' * 5, 'V'),
        Abbreviation('DCCCC', 'CM'),
        Abbreviation('CCCC', 'CD'),
        Abbreviation('LXXXX', 'XC'),
        Abbreviation('XXXX', 'XL'),
        Abbreviation('VIIII', 'IX'),
        Abbreviation('IIII', 'IV')
    ]
    
    
    def to_roman(arabic):
        roman = 'I' * arabic
        for abbr in abbreviations:
            roman = roman.replace(abbr.long, abbr.short)
    
        return roman
    

    I like its simplicity! No need for modulo operations, conditionals, or multiple loops. Of course, you don't need namedtuples either; you can use plain tuples or lists instead.

    0 讨论(0)
  • 2020-11-30 12:37

    A KISS version of Manhattan's algorithm, without any "advanced" notion such as OrderedDict, recursion, generators, inner function and break:

    ROMAN = [
        (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"),
    ]
    
    def int_to_roman(number):
        result = ""
        for (arabic, roman) in ROMAN:
            (factor, number) = divmod(number, arabic)
            result += roman * factor
        return result
    

    A prematurate exit could be added as soon as number reaches zero, and the string accumulation could be made more pythonic, but my goal here was to produce the requested basic program.

    Tested on all integers from 1 to 100000, which ought to be enough for anybody.

    EDIT: the slightly more pythonic and faster version I alluded to:

    def int_to_roman(number):
        result = []
        for (arabic, roman) in ROMAN:
            (factor, number) = divmod(number, arabic)
            result.append(roman * factor)
            if number == 0:
                break
        return "".join(result)
    
    0 讨论(0)
  • 2020-11-30 12:37

    Interesting question. Several approaches but haven't seen this one yet. We can trade execution time for memory, and reduce potential for pesky arithmetic errors (off-by-one, int vs float div, etc).

    Each arabic digit (1s, 10s, 100s, etc) translates to a unique Roman sequence. So just use a lookup table.

    ROMAN = {
        0 : ['', 'm', 'mm', 'mmm'],
        1 : ['', 'c', 'cc', 'ccc', 'cd', 'd', 'dc', 'dcc', 'dccc', 'cm'],
        2 : ['', 'x', 'xx', 'xxx', 'xl', 'l', 'lx', 'lxx', 'lxxx', 'xc'],
        3 : ['', 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix'],
    }
    
    def to_roman (num, lower = True):
        '''Return the roman numeral version of num'''
        ret = ''
        digits = '%04d' % num
        for pos, digit in enumerate (digits):
            ret += ROMAN [pos] [int (digit)]
        return lower and ret or ret.upper ()
    

    You can add checks for 0 > num > 4000, but not necessary as lookup will fail on int conversion for '-' or index out of range. I prefer lowercase, but upper available as well.

    Digit selection could be done arithmetically, but algorithm becomes a bit trickier. Lookups are simple and effective.

    0 讨论(0)
  • 2020-11-30 12:37

    The code for this roman numeral does not check for errors like wrong letters it is just for a perfect roman numeral letters

    roman_dict = {'M':1000, 'CM':900, 'D':500, 'CD':400, 'C':100, 'XC':90,
             'L':50, 'XL':40, 'X':10, 'IX':9, 'V':5, 'IV':4,'I':1}
    
    roman = input('Enter the roman numeral: ').upper()
    roman_initial = roman # used to retain the original roman figure entered
    
    lst = []
    
    
    while roman != '':    
    if len(roman) > 1:
        check = roman[0] + roman[1]
        if check in roman_dict and len(roman) > 1:
            lst.append(check)
            roman = roman[roman.index(check[1])+1:]
        else:
            if check not in roman_dict and len(roman) > 1:
                lst.append(check[0])
                roman = roman[roman.index(check[0])+1:]   
    else:
        if len(roman)==1:
            check = roman[0]
            lst.append(check[0])
            roman = ''
    
    if lst != []:
    Sum = 0
    for i in lst:
        if i in roman_dict:
            Sum += roman_dict[i]
    print('The roman numeral %s entered is'%(roman_initial),Sum)
    
    0 讨论(0)
  • 2020-11-30 12:38

    When you use the def keyword, you just define a function, but you don't run it.

    what you're looking for is something more like this:

    def generate_all_numerals(n): 
    ...
    
    def to_roman(n):
    ...
    
    print "This program ..."
    n = raw_input("Enter...")
    
    print to_roman(n)
    

    welcome to python :)

    0 讨论(0)
提交回复
热议问题