How to resolve the algorithm Roman numerals/Encode step by step in the Python programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Roman numerals/Encode step by step in the Python programming language

Table of Contents

Problem Statement

Create a function taking a positive integer as its parameter and returning a string containing the Roman numeral representation of that integer. Modern Roman numerals are written by expressing each digit separately, starting with the left most digit and skipping any digit with a value of zero.

In Roman numerals:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Roman numerals/Encode step by step in the Python programming language

Python Code to Convert Arabic Numbers to Roman Numerals

The given Python code provides multiple functions to convert Arabic numbers to their corresponding Roman numeral representations. Here's a detailed explanation of each function:

Function 1: roman.toRoman(n)

This function converts an integer n to its Roman numeral representation.

  • It initializes res as an empty string to store the Roman numeral result.
  • It sets reg equal to n.
  • It iterates through different Roman numerals (M, D, C, L, X, V, I) in decreasing order.
  • Within each iteration, it checks if reg is greater than or equal to the current Roman numeral value.
  • If reg is greater than or equal, it appends the corresponding Roman numeral to res and subtracts its Arabic value from reg.
  • This process continues until reg becomes 0.
  • Finally, the function returns the res string representing the Roman numeral for n.

Function 2: toRoman(n)

This function is similar to roman.toRoman but follows a slightly different approach.

  • It initializes res as an empty string to store the Roman numeral result.
  • It initializes reg as n.
  • It iterates through different Roman numerals in decreasing order, similar to the roman.toRoman function.
  • For each Roman numeral, it checks if reg is greater than or equal to the current Roman numeral value.
  • If reg is greater than or equal, it appends the corresponding Roman numeral to res and subtracts its Arabic value from reg.
  • The process continues until reg becomes 0.
  • The function returns the res string representing the Roman numeral for n.

Function 3: arabic_to_roman(dclxvi)

This function converts an integer dclxvi to its Roman numeral representation. It uses a different algorithm compared to the previous functions.

  • It stores the original value of dclxvi in org.
  • It initializes out as an empty string to store the Roman numeral result.
  • It iterates through a list of Arabic numbers (corresponding to M, D, C, L, X, V, I) and their corresponding Roman numerals (stored in roman).
  • For each Arabic number, it calculates the quotient and remainder when org is divided by the Arabic number.
  • It appends the corresponding Roman numeral to out based on the quotient and remainder.
  • It then adjusts the org value based on the Roman numeral and Arabic number used.
  • This process continues until org becomes 0.
  • Finally, the function returns the out string representing the Roman numeral for dclxvi.

Function 4: ToRoman(num)

This function converts an integer num to its Roman numeral representation.

  • It initializes namoR as an empty string to store the Roman numeral result.
  • It iterates through a list of Roman numerals in pairs.
  • For each pair of Roman numerals (e.g., "IV" and "V"), it calculates the quotient and remainder when num is divided by the Arabic value of the first Roman numeral.
  • It appends the corresponding Roman numerals to namoR based on the quotient and remainder.
  • It then adjusts the num value based on the Roman numerals used.
  • This process continues until num becomes 0.
  • Finally, it returns namoR string representing the Roman numeral for num.

Function 5: to_roman(x)

This function converts an integer x to its Roman numeral representation.

  • It initializes an empty list ret to store the Roman numeral result.
  • It iterates through a list of Arabic numbers in decreasing order.
  • For each Arabic number, it calculates the quotient and remainder when x is divided by the Arabic number.
  • It appends the corresponding Roman numeral to ret based on the quotient.
  • It then adjusts the x value based on the Roman numeral and Arabic number used.
  • This process continues until x becomes 0.
  • Finally, the function returns the concatenated string of ret representing the Roman numeral for x.

Function 6: arabic_to_roman(dclxvi)

This function is similar to arabic_to_roman(dclxvi) from before but uses a slightly different implementation.

  • It stores the original value of dclxvi in org.
  • It initializes out as an empty string to store the Roman numeral result.
  • It iterates through a list of Arabic numbers (corresponding to M, D, C, L, X, V, I) and their corresponding Roman numerals (stored in roman).
  • For each Arabic number, it calculates the quotient and remainder when org is divided by the Arabic number.
  • It appends the corresponding Roman numeral to out based on the quotient and remainder.
  • It then adjusts the org value based on the Roman numeral and Arabic number used.
  • This process continues until org becomes 0.
  • Finally, the function returns the out string representing the Roman numeral for dclxvi.

Function 7: number2romannumeral(n)

This function converts an integer n to its Roman numeral representation.

  • Option 1: It converts n to a 4-digit string, fills zeros if necessary, and then maps each digit to its corresponding Roman numeral.
  • Option 2: It uses mapAccumL to accumulate the Roman numeral representations of each digit in n.

Function 8: romanFromInt(n)

This function converts an integer n to its Roman numeral representation.

  • It uses a recursive go function to accumulate the Roman numeral representation by dividing n by Roman numeral values and concatenating the corresponding Roman numerals.

Overall, these functions provide various approaches to convert Arabic numbers to Roman numeral representations. They illustrate different algorithms and techniques for handling this conversion task.

Source code in the python programming language

import roman
print(roman.toRoman(2022))

def toRoman(n):
    res=''		#converts int to str(Roman numeral)
    reg=n		#using the numerals (M,D,C,L,X,V,I)
    if reg<4000:#no more than three repetitions
        while reg>=1000:	#thousands up to MMM
            res+='M'		#MAX is MMMCMXCIX
            reg-=1000		
        if reg>=900:		#nine hundreds in 900-999
            res+='CM'
            reg-=900
        if reg>=500:		#five hudreds in 500-899
            res+='D'
            reg-=500
        if reg>=400:		#four hundreds in 400-499
            res+='CD'
            reg-=400
        while reg>=100:		#hundreds in 100-399
            res+='C'
            reg-=100
        if reg>=90:			#nine tens in 90-99
            res+='XC'
            reg-=90
        if reg>=50:			#five Tens in 50-89
            res+='L'
            reg-=50
        if reg>=40:
            res+='XL'		#four Tens
            reg-=40
        while reg>=10:
            res+="X"		#tens
            reg-=10
        if reg>=9:
            res+='IX'		#nine Units
            reg-=9
        if reg>=5:
            res+='V'		#five Units
            reg-=5
        if reg>=4:
            res+='IV'		#four Units
            reg-=4
        while reg>0:		#three or less Units
            res+='I'
            reg-=1
    return res

roman =        "MDCLXVmdclxvi"; # UPPERCASE for thousands #
adjust_roman = "CCXXmmccxxii";
arabic =       (1000000, 500000, 100000, 50000, 10000, 5000, 1000, 500, 100, 50, 10, 5, 1);
adjust_arabic = (100000, 100000,  10000, 10000,  1000, 1000,  100, 100,  10, 10,  1, 1, 0);

def arabic_to_roman(dclxvi):
  org = dclxvi; # 666 #
  out = "";
  for scale,arabic_scale  in enumerate(arabic): 
    if org == 0: break
    multiples = org / arabic_scale;
    org -= arabic_scale * multiples;
    out += roman[scale] * multiples;
    if org >= -adjust_arabic[scale] + arabic_scale: 
      org -= -adjust_arabic[scale] + arabic_scale;
      out +=  adjust_roman[scale] +  roman[scale]
  return out
 
if __name__ == "__main__": 
  test = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,30,40,50,60,69,70,
     80,90,99,100,200,300,400,500,600,666,700,800,900,1000,1009,1444,1666,1945,1997,1999,
     2000,2008,2500,3000,4000,4999,5000,6666,10000,50000,100000,500000,1000000);
  for val in test: 
    print '%d - %s'%(val, arabic_to_roman(val))

romanDgts= 'ivxlcdmVXLCDM_'

def ToRoman(num):
   namoR = ''
   if num >=4000000:
      print 'Too Big -'
      return '-----'
   for rdix in range(0, len(romanDgts), 2):
      if num==0: break
      num,r = divmod(num,10)
      v,r = divmod(r, 5)
      if r==4:
         namoR += romanDgts[rdix+1+v] + romanDgts[rdix]
      else:
         namoR += r*romanDgts[rdix] + (romanDgts[rdix+1] if(v==1) else '')
   return namoR[-1::-1]

anums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
rnums = "M CM D CD C XC L XL X IX V IV I".split()

def to_roman(x):
    ret = []
    for a,r in zip(anums, rnums):
        n,x = divmod(x,a)
        ret.append(r*n)
    return ''.join(ret)
        
if __name__ == "__main__":
    test = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,30,40,
            50,60,69,70,80,90,99,100,200,300,400,500,600,666,700,800,900,
            1000,1009,1444,1666,1945,1997,1999,2000,2008,2010,2011,2500,
            3000,3999)
    
    for val in test:
        print '%d - %s'%(val, to_roman(val))

def arabic_to_roman(dclxvi):
#===========================
  '''Convert an integer from the decimal notation to the Roman notation'''
  org = dclxvi; # 666 #
  out = "";
  for scale, arabic_scale  in enumerate(arabic):
    if org == 0: break
    multiples = org // arabic_scale;
    org -= arabic_scale * multiples;
    out += roman[scale] * multiples;
    if (org >= -adjust_arabic[scale] + arabic_scale):
      org -= -adjust_arabic[scale] + arabic_scale;
      out +=  adjust_roman[scale] +  roman[scale]
  return out

if __name__ == "__main__": 
  test = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,30,40,50,60,69,70,
     80,90,99,100,200,300,400,500,600,666,700,800,900,1000,1009,1444,1666,1945,1997,1999,
     2000,2008,2500,3000,4000,4999,5000,6666,10000,50000,100000,500000,1000000);
  
  for val in test: 
    print("%8d %s" %(val, arabic_to_roman(val)))

rnl = [ { '4' : 'MMMM', '3' : 'MMM', '2' : 'MM', '1' : 'M', '0' : '' }, { '9' : 'CM', '8' : 'DCCC', '7' : 'DCC',
          '6' : 'DC', '5' : 'D', '4' : 'CD', '3' : 'CCC', '2' : 'CC', '1' : 'C', '0' : '' }, { '9' : 'XC',
          '8' : 'LXXX', '7' : 'LXX', '6' : 'LX', '5' : 'L', '4' : 'XL', '3' : 'XXX', '2' : 'XX', '1' : 'X',
          '0' : '' }, { '9' : 'IX', '8' : 'VIII', '7' : 'VII', '6' : 'VI', '5' : 'V', '4' : 'IV', '3' : 'III',
          '2' : 'II', '1' : 'I', '0' : '' }]
# Option 1
def number2romannumeral(n):
    return ''.join([rnl[x][y] for x, y in zip(range(4), str(n).zfill(4)) if n < 5000 and n > -1])
# Option 2
def number2romannumeral(n):
    return reduce(lambda x, y: x + y, map(lambda x, y: rnl[x][y], range(4), str(n).zfill(4))) if -1 < n < 5000 else None

'''Encoding Roman Numerals'''

from functools import reduce
from itertools import chain


# romanFromInt ::  Int -> String
def romanFromInt(n):
    '''A string of Roman numerals encoding an integer.'''
    def go(a, ms):
        m, s = ms
        q, r = divmod(a, m)
        return (r, s * q)

    return concat(snd(mapAccumL(go)(n)(
        zip([
            1000, 900, 500, 400, 100, 90, 50,
            40, 10, 9, 5, 4, 1
        ], [
            'M', 'CM', 'D', 'CD', 'C', 'XC', 'L',
            'XL', 'X', 'IX', 'V', 'IV', 'I'
        ])
    )))


# ------------------------- TEST -------------------------
# main :: IO ()
def main():
    '''Sample of years'''
    for s in [
            romanFromInt(x) for x in [
                1666, 1990, 2008, 2016, 2018, 2020
            ]
    ]:
        print(s)


# ------------------ GENERIC FUNCTIONS -------------------

# concat :: [[a]] -> [a]
# concat :: [String] -> String
def concat(xxs):
    '''The concatenation of all the elements in a list.'''
    xs = list(chain.from_iterable(xxs))
    unit = '' if isinstance(xs, str) else []
    return unit if not xs else (
        ''.join(xs) if isinstance(xs[0], str) else xs
    )


# mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
def mapAccumL(f):
    '''A tuple of an accumulation and a list derived by a
       combined map and fold,
       with accumulation from left to right.'''
    def go(a, x):
        tpl = f(a[0], x)
        return (tpl[0], a[1] + [tpl[1]])
    return lambda acc: lambda xs: (
        reduce(go, xs, (acc, []))
    )


# snd :: (a, b) -> b
def snd(tpl):
    '''Second component of a tuple.'''
    return tpl[1]


# MAIN ---
if __name__ == '__main__':
    main()

  

You may also check:How to resolve the algorithm Hofstadter Figure-Figure sequences step by step in the Julia programming language
You may also check:How to resolve the algorithm Amicable pairs step by step in the Common Lisp programming language
You may also check:How to resolve the algorithm First-class functions step by step in the M2000 Interpreter programming language
You may also check:How to resolve the algorithm Unbias a random generator step by step in the Haskell programming language
You may also check:How to resolve the algorithm Identity matrix step by step in the ALGOL W programming language