Home > database >  List comprehension for int to roman numeral
List comprehension for int to roman numeral

Time:04-05

I have a function roman(x) that takes an int (>= 1) and returns the roman numeral as a string. I have achieved a working example with:

def roman(x: int) -> str:
    """Convert into to roman numeral"""
    
    L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
         (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
         (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

    y = ""
    for val, sym in L:
        y  = sym*(x//val)
        x -= val*(x//val)

    return y
>>> roman(399)
'CCCXCIX'

I am asking how to convert the for loop:

y = ""
for val, sym in L:
    y  = sym*(x//val)
    x -= val*(x//val)

return y

Into a list comprehension

return "".join([ ... ])

L Does not need to be embedded into the list comprehension, and can remain as is. Such that the function is in this form:

def roman(x: int) -> str:
    """Convert into to roman numeral"""

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

    # Return list comprehension as a string
    return "".join([ ... ])

CodePudding user response:

If you don't mind recursion, this is actually a pretty good use case for it.

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

def roman(num):
  if num == 0: # Base case: when we reach zero, return empty string
    return ''
  # Recursive step: iterate over values and their characters
  for v, n in L:
    if num >= v: # If their difference is positive, we recurse
      return n   roman(num - v) # We append the result to the numeral

roman(399)
>> 'CCCXCIX'

CodePudding user response:

Version using functools.reduce

from functools import reduce

def roman(x: int) -> str:
    """Convert into to roman numeral"""

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

    return reduce(lambda s, c: (s[0]   c[1]*(s[1]//c[0]), s[1] - c[0]*(s[1]//c[0])), L, ("", x))[0]

print(roman(399)) # CCCXCIX

It's scary, it's unreadable. Don't use it

CodePudding user response:

Since Python lacks the power of pointers, to use "".join([]) as your requirement, I think this code can be your solution

def roman(x: int) -> str:
    """Convert into to roman numeral"""
    
    L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
         (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
         (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]
    L = dict(L)
    x = [x]
    def custum_mul(x,k):
        temp = x[0]//k
        x[0]-= k*(x[0]//k)
        return temp
    y = "".join([v*(custum_mul(x,k)) for k,v in L.items()])
    return y

out = roman(399)
print(out) # CCCXCIX

However, it's long, complex, and hard to understand so don't use it.

  • Related