Convert decimals to Roman numerials. I use a recursive algorithm here since it reflects the thinking clearly in code. A non-recursive algothrithm can be done as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | """
Victor Yang, pythonrocks@yahoo.com
Convert decimals to Roman numerials.
I use a recursive algorithm here since it reflects the thinking clearly in code.
A non-recursive algothrithm can be done as well.
usage: python roman.py
It will run the test case against toRoman function
"""
import sys
import unittest
# these two lists serves as building blocks to construt any number
# just like coin denominations.
# 1000->"M", 900->"CM", 500->"D"...keep on going
decimalDens=[1000,900,500,400,100,90,50,40,10,9,5,4,1]
romanDens=["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
def toRoman(dec):
"""
Perform sanity check on decimal and throws exceptions when necessary
"""
if dec <=0:
raise ValueError, "It must be a positive"
# to avoid MMMM
elif dec>=4000:
raise ValueError, "It must be lower than MMMM(4000)"
return decToRoman(dec,"",decimalDens,romanDens)
def decToRoman(num,s,decs,romans):
"""
convert a Decimal number to Roman numeral recursively
num: the decimal number
s: the roman numerial string
decs: current list of decimal denomination
romans: current list of roman denomination
"""
if decs:
if (num < decs[0]):
# deal with the rest denomination
return decToRoman(num,s,decs[1:],romans[1:])
else:
# deduce this denomation till num<desc[0]
return decToRoman(num-decs[0],s+romans[0],decs,romans)
else:
# we run out of denomination, we are done
return s
class DecToRomanTest(unittest.TestCase):
def setUp(self):
print '\nset up'
def tearDown(self):
print 'tear down'
def testDens(self):
for i in range(len(decimalDens)):
r=toRoman(decimalDens[i])
self.assertEqual(r,romanDens[i])
def testSmallest(self):
self.assertEqual('I',toRoman(1))
def testBiggest(self):
self.assertEqual('MMMCMXCIX',toRoman(3999))
def testZero(self):
self.assertRaises(ValueError,toRoman,0)
def testNegative(self):
self.assertRaises(ValueError,toRoman,-100)
def testMillonDollar(self):
self.assertRaises(ValueError,toRoman,1000000)
if __name__ == "__main__":
unittest.main()
|
Just for fun.
Tags: algorithms
For grins: A non-recursive version.
Now it's Online. I made this recipe into an online utility. Check it out:
http://www.utilitymill.com/utility/Decimal_to_Roman_Numerals