Roman Numerals

Examples of: input(), int(), functions, global, if, while, list, dictionary, for, in, range,=, >=, +, print()

The first and only time I ever got to go to a Python User’s meeting I did not know I was supposed to bring my laptop.  The challenge was to write a program that would take any integer (maximum 5000) and convert it to a Roman Numeral. Error checking was excused for this exercise.  It seemed to me the point was to get everybody trying code, almost blindly, in small segments immediately.

I’m glad I did not have my laptop at this meeting.

When I was taught to program in Fortran, Cobol and Basic in college the first thing we always did was to (1) think about the process and write it out in English and then to (2) flowchart the process – actually draw a picture of what was to happen.  Don’t programmers still do that?  Our general rule of thumb was that a minute of planning was worth two hours of programming.

Anyway, nobody came up with a solution that night.  I went home and did it the old way, coming up with the following in about 2 hours.  Here is A solution (definitely not THE solution) that works and seems fairly efficient to me.   Later, I took this solution and converted it to a GUI program using tkinter as an example of GUI structure and deployment.  You will find that example listed separately.



_author_ = "John Oakey"
getnum = input("Enter a number between 1 and 5000:  ")
NumIn = int(getnum)
AmtLeft=NumIn
RN = "" #Roman Numeral - build string here
#For most of the number we use this function to build our string
def resolvetest (_lefttest, _string,):
    global AmtLeft, RN
    if AmtLeft >= _lefttest:
        RN = RN + _string
        AmtLeft = AmtLeft - _lefttest
#(1) But First we will pull out the thousands because it is easier
while AmtLeft >= 1000:
    RN = RN+"M"
    AmtLeft = AmtLeft - 1000
#We put the break points down to 9 in a table, and break points with paired string parts in a dictionary
#dictionaries are not iterable, but list are:  alternatively we could have used a list of tuples like tuplist =[(900,'CM'),(800,'DCCC'),(700,'DCC'),(600,'DC')...etc]
rtt=(900,800,700,600,500,400,300,200,100,90,80,70,60,50,40,30,20,10,9)
rtd={900:"CM",800:"DCCC",700:"DCC",600:"DC",500:"D",400:"CD",300:"CCC",200:"CC",100:"C",90:"XC",80:"LXXX",70:"LXX",60:"LX",50:"L",40:"XL",30:"XXX",20:"XX",10:"X",9:"IX"}
#now we crank up the routine that does most of the hard work, taking us down to and including a remainder of 9
for index in range(len(rtt)): #we send each breakpoint and its concomitant string to the resolvetest function
    resolvetest(rtt[index], rtd[rtt[index]])
#(2) We hand 9 to 5 as a special case
if AmtLeft >=5:
    RN=RN+"V"
    AmtLeft = AmtLeft-5
    for i in range (AmtLeft):
        RN = RN + "I"
        AmtLeft = AmtLeft-1
#(3) Send the value 4 to the function, if amount left is not 4 nothing will process
resolvetest(4,"IV")
#(4) Resolve 3 to 1 as a special case.
while AmtLeft >=1:
    RN = RN + "I"
    AmtLeft = AmtLeft - 1

print("The number in: ",NumIn)
print("The Roman Numberal :", RN)
if AmtLeft > 0:
    print("Left over error: ",AmtLeft)