The Republic, Julius Caesar, The Colosseum. Yes, I'm talking about Ancient Rome. A few days ago I read Conn Iggulden's book about Caesar successor, Octavian and remembered the CheckiO mission "Roman Numerals". So let's look revisit this numeral system.

Roman numerals come from the ancient Roman numbering system. They are based on specific letters of the alphabet which are combined to signify the sum (or, in some cases, the difference) of their values. The first ten Roman numerals are:

I, II, III, IV, V, VI, VII, VIII, IX, X

The Roman numeral system is decimal based, but not directly positional and does not include a zero. Roman numerals are based on combinations of these seven symbols:

Simple Solution

We can single out "elemental" numbers and break the given number at these elements top down. Here is those "elements" for the roman numerals:

"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

Next we try to subtract these numbers from the given until we can. And connect characters from left to right. The result is our number in roman form.

ELEMENTS = (( "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 )) def checkio(number): result = "" for roman, n in ELEMENTS : if n <= number: result += roman * (number // n) number %= n return result

"Clear" Solutions

In the "Clear" category, @JulianNicholls's "First" solution has earned many player votes and uses simple clear algorithm.

The next is Mark Pilgrim's realisation written by @macfreek. This solution is like the previous one but with comments and other "production" features.

"Creative" solutions (just for fun)

How about a veeeery long one-liner from @ciel?

checkio=lambda data: [ '','M','MM','MMM' ][ data//1000 ]+[ '','C','CC','CCC','CD','D','DC','DCC','DCCC','CM' ][ data//100%10 ]+[ '','X','XX','XXX','XL','L','LX','LXX','LXXX','XC' ][ data//10%10 ]+[ '','I','II','III','IV','V','VI','VII','VIII','IX' ][ data%10 ]

Or "Recursive, short, weird but works! :)" by @hrvoje.

def checkio (data) : s = lambda b,z: '' if not z else str (s(b%z[ 0 ][ 0 ], z[ 1 :]) ) + (b//z[ 0 ][ 0 ]) *z[0][1] return s (data, [( 1000 , 'M' ) , ( 900 , 'MC' ) , ( 500 , 'D' ) , ( 400 , 'DC' ) , ( 100 , 'C' ) , ( 90 , 'CX' ) , ( 50 , 'L' ) , ( 40 , 'LX' ) , ( 10 , 'X' ) , ( 9 , 'XI' ) , ( 5 , 'V' ) , ( 4 , 'VI' ) , ( 1 , 'I' ) ])[::-1]

Or even the puzzler "dict FTW" from @veky instead of a weekend crossword for you.

def checkio (x) : a,r= "" ,{} for i in range( 3 ): p,(j,c,d)= 10 **i, "IVXLCDM" [ 2 *i:][: 3 ] r.update({p:j, 5 *p:c, 4 *p:j+c, 9 *p:j+d, 10 *p:d}) for k in reversed(sorted(r)): a+=x//k*r[k] x%=k return a

That's all folks. Maybe you would like to review some CiO mission?

Valentin Bryukhanov aka Bryukh