0

Let Python do the work for you and figure out the roman numerals for a given integer. I have to ask you to keep the integer values somewhat reasonably low (from 1 to 4999), since roman numerals from 5000 on use characters with an overline and most PCs don't have those in the character set.

Edited by vegaseat: n/a

# convert an integer to a roman numeral
# keep it reasonable since from 5000 on special characters are used
# see also: http://en.wikipedia.org/wiki/Roman_numerals
# tested with Python24       vegaseat        25jan2007

def int2roman(number):
    numerals = { 1 : "I", 4 : "IV", 5 : "V", 9 : "IX", 10 : "X", 40 : "XL", 
        50 : "L", 90 : "XC", 100 : "C", 400 : "CD", 500 : "D", 900 : "CM", 1000 : "M" }
    result = ""
    for value, numeral in sorted(numerals.items(), reverse=True):
        while number >= value:
            result += numeral
            number -= value
    return result

print int2roman(input("Enter an integer (1 to 4999): "))

"""
Enter an integer (1 to 4999): 2007
MMVII
"""
6
Contributors
11
Replies
15
Views
10 Years
Discussion Span
Last Post by eljakim
0

i'm just playing around with python and decided to try this code out but keep getting a syntax error pointing to the colon after the 1 in,

0

I just tested it with python 2.6 and it works. For python 3.1, I had to change the last statement to

print(int2roman(int(input("Enter an integer (1 to 4999): "))))

and it works.

0

@pythonuser18
you used () instead of {}
a dictionary container needs the curly braces.

0
def DecToRom (number) :
    numerals={1: "I", 4: "IV", 5: "V", 9: "IX", 10: "X", 40: "XL", 50: "L", 90: "XC", 100: "C", 400: "CD", 500: "D", 900: "CM", 1000: "M"}
    result=""
    for value, numeral in sorted(numerals.items(), reverse=True):
        while number >= value:
            result += numeral
            number -= value
    return result
print DecToRom(raw_input(“Decimal number: “))

could someone tell me why this isn't working? It says Syntax Error: invalid syntax

I know the indents aren't formatted correctly on this post, but they are as they are suppose to be in python

Edited by Dani: Formatting fixed

1

Roman to integer. Note that it will take something like XXIXV and convert it. If someone already has a routine to check for valid input, please post it. And I'm afraid we've just eliminated one standard homework question. Oh well, nothing lasts forever.

roman_to_decimal = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, \
                     'D': 500, 'M': 1000 }

roman = raw_input("Enter the roman numeral to convert to arabic: ").upper()

converted = True
arabic = 0
for n in range(0, len(roman)-1):
    this_char = roman[n]
    next_char = roman[n+1]
    if (this_char in roman_to_decimal) and \
       (next_char in roman_to_decimal):

        this_number = roman_to_decimal[this_char]
        next_number =  roman_to_decimal[next_char]
        print "converting %s to %d....." % (this_char, this_number),
        if this_number < next_number:
            arabic -= this_number
        else:
            arabic += this_number
        print "Total now =", arabic

    else:
        print "\nthis chr (%s) or next chr (%s) is not a valid roman numeral" \
              % (this_char, next_char)
        converted = False
        break

if converted:
    ##  add last roman numeral
    arabic += roman_to_decimal[roman[len(roman)-1]]

    print "\nThe roman numeral", roman, "is equal to",arabic
0

A quick solution that does both directions:

# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

mapping = [ ('cd','cccc'), ('xl','xxxx'),('iv','iiii'),('d','ccccc'),('l','xxxxx'),('v','iiiii'), ('cm','ccccccccc'), ('xc','xxxxxxxxx'),('ix','iiiiiiiii')]
mapping.reverse()
bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

def fromroman(x):
	for (kort, lang) in mapping: x= x.replace(kort, lang)
	x = '+'.join(list(x))
	for (karakter, waarde) in bignums: x = x.replace(karakter, str(waarde))
	if x=='': x = '0'
	return eval(x)

def toroman(x):
	val = ''
	for (karakter, waarde) in bignums:
		val = val + (x / waarde) * karakter
		x = x % waarde
	for (kort, lang) in mapping: 
		val = val.replace(lang,kort)
	return val
0

Nice concept but fails in execution:

# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

# bug testing, translation of variables and reformating
# Tony Veijalainen 2010-06-16

mapping = [ ('cd','cccc'),
            ('xl','xxxx'),
            ('iv','iiii'),
            ('d','ccccc'),
            ('l','xxxxx'),
            ('v','iiiii'),
            ('cm','ccccccccc'),
            ('xc','xxxxxxxxx'),
            ('ix','iiiiiiiii')]


mapping.reverse()
bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

def fromroman(x):
	for (shortv, longv) in mapping: x= x.replace(shortv, longv)
	x = '+'.join(list(x))
	for (character, word) in bignums: x = x.replace(character, str(word))
	if x=='': x = '0'
	return eval(x)

def toroman(x):
	val = ''
	for (character, word) in bignums:
		val = val + (x / word) * character
		x = x % word
	for (shortv, longv) in mapping: 
		val = val.replace(longv,shortv)
	return val

for i in range(5000):
    if fromroman(toroman(i)) != i:
        print ('Bug found: %i, %s, %s' % (i,toroman(i),fromroman(toroman(i))))

The code gives plenty of bugs printed.

Edited by pyTony: n/a

1

Got it passing my test by rearranging the values that were present in bug cases in the mapping (cleaned up multiletter expressions by *):

# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

# bug testing, translation of variables and reformating
# Tony Veijalainen 2010-06-16

mapping = [ ('d',5*'c'),
            ('l',5*'x'),
            ('v',5*'i'),
            ('cm',9*'c'),
            ('xc',9*'x'),
            ('ix',9*'i'),
            ('cd',4*'c'),
            ('iv',4*'i'),
            ('xl',4*'x')]


mapping.reverse()
bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

def fromroman(x):
	for (shortv, longv) in mapping: x= x.replace(shortv, longv)
	x = '+'.join(list(x))
	for (character, word) in bignums: x = x.replace(character, str(word))
	if x=='': x = '0'
	return eval(x)

def toroman(x):
	val = ''
	for (character, word) in bignums:
		val = val + (x / word) * character
		x = x % word
	for (shortv, longv) in mapping: 
		val = val.replace(longv,shortv)
	return val

bugs=0
for i in range(5000):
    if fromroman(toroman(i)) != i:
        print ('Bug found: %i, %s, %s' % (i,toroman(i),fromroman(toroman(i))))
        bugs+=1

print(('Number of bugs found: %i' % bugs) if bugs else 'Test passed!')


""" Output:
Test passed!
"""

Edited by pyTony: n/a

Comments
sharp mind
0

Correct fix is take out permanent reverse and use reversed() in to roman translation:

# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

mapping = [ ('cd',4*'c'),
            ('xl',4*'x'),
            ('iv',4*'i'),
            ('d',5*'c'),
            ('l',5*'x'),
            ('v',5*'i'),
            ('cm',9*'c'),
            ('xc',9*'x'),
            ('ix',9*'i')]

bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

## vegaseat function for error check
def int2roman(number):
    numerals = { 1 : "I", 4 : "IV", 5 : "V", 9 : "IX", 10 : "X", 40 : "XL", 
        50 : "L", 90 : "XC", 100 : "C", 400 : "CD", 500 : "D", 900 : "CM", 1000 : "M" }
    result = ""
    for value, numeral in sorted(numerals.items(), reverse=True):
        while number >= value:
            result += numeral
            number -= value
    return result

def fromroman(x):
	for (shortv, longv) in mapping: x= x.replace(shortv, longv) ## reverse order needed
	x = '+'.join(list(x))
	for (character, word) in bignums: x = x.replace(character, str(word))
	if x=='': x = '0'
	return eval(x)

def toroman(x):
	val = ''
	for (character, word) in bignums:
		val = val + (x / word) * character
		x = x % word
	for (shortv, longv) in reversed(mapping): ## reverse here not permanantly
		val = val.replace(longv,shortv)
	return val

bugs1 = bugs2 = 0
for i in range(5000):
    if fromroman(toroman(i)) != i:
        print ('Reverse failure: %i, %s, %s' % (i,toroman(i),fromroman(toroman(i))))
        bugs1+=1

    if  int2roman(i).lower() != toroman(i): 
        print ('Wrong roman: %i, %s, %s' % (i,int2roman(i),toroman(i)))
        bugs2+=1

print(('Number of bugs found: %i reverse failure, %i wrong roman' % (bugs1,bugs2) if bugs1 + bugs2 else 'Test passed!'))
""" Last ilne of output:
Test passed!
"""

Edited by pyTony: n/a

0

I am quite embarrassed at the low quality I produced in the middle of the night.

Thank you for fixing it.

Eljakim

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.