Skip to content

Instantly share code, notes, and snippets.

@davidtweaver
Created June 10, 2013 19:36
Show Gist options
  • Save davidtweaver/5751559 to your computer and use it in GitHub Desktop.
Save davidtweaver/5751559 to your computer and use it in GitHub Desktop.
Numbers to Roman Numerals
import unittest
KNOWN_VALUES = [
(1, 'I'),
(5, 'V'),
(10,'X'),
(50,'L'),
(100,'C'),
(500,'D'),
(1000,'M'),
(2, "II"),
(3, "III"),
(4, "IV"),
(200,"CC"),
(9, "IX"),
(207, "CCVII"),
(1904, "MCMIV"),
(1954, "MCMLIV"),
(2013, "MMXIII"),
(400, "CD"),
(900, "CM"),
(10000, "MMMMMMMMMM"),
]
SYMBOLS = [
(1, 'I'),
(5, 'V'),
(10,'X'),
(50,'L'),
(100,'C'),
(500,'D'),
(1000,'M'),
]
def convert(number):
big_string = number*'I'
return big_string_to_small(big_string)
def big_string_to_small(big_string):
"""
>>> big_string_to_small('I'*1000)
'M'
>>> big_string_to_small('I'*500)
'D'
>>> big_string_to_small('I'*100)
'C'
>>> big_string_to_small('I'*105)
'CV'
"""
result = big_string
for (number, text) in reversed(SYMBOLS):
if number*'I' in result:
# Replace all runs of "I" with the appropriate symbol
result = result.replace(number*'I',text)
#print result
return replace_repeats(result)
def replace_repeats(roman):
"""
>>> replace_repeats('IIII')
'IV'
>>> replace_repeats('XXXX')
'XL'
>>> replace_repeats(convert(404))
'CDIV'
"""
result = roman
for (_, smaller), (_, bigger) in zip(SYMBOLS, SYMBOLS[1:]):
if 4*smaller in result:
target = "{}{}".format(smaller, bigger)
result = result.replace(4*smaller, target)
return result
class KnownGood(unittest.TestCase):
def __init__(self, input, output):
super(KnownGood, self).__init__()
self.input = input
self.output = output
def runTest(self):
self.assertEqual(convert(self.input), self.output)
def make_suite():
suite = unittest.TestSuite()
suite.addTests(KnownGood(input, output) for input, output in KNOWN_VALUES)
return suite
if __name__ == '__main__':
unittest.TextTestRunner().run(make_suite())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment