1
votes

Python - Convertit un chiffre romain en entier

J'ai essayé le code Python 3 suivant qui transforme de Roman en Integer.

Le code fonctionne très bien en un coup d'œil. Mais il y a un certain problème lorsque j'entre X , V ou lié aux valeurs X et V

Par exemple: quand j'essaye V le code ne fonctionne pas mais pour IV montrant la valeur correcte.

Mon code:

class Solution(object):
   def romanToInt(self, s):
      """
      :type s: str
      :rtype: int
      """
      roman = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000,'IV':4,'IX':9,'XL':40,'XC':90,'CD':400,'CM':900}
      i = 0
      num = 0
      while i < len(s):
         if i+1<len(s) and s[i:i+2] in roman:
            num+=roman[s[i:i+2]]
            i+=2
         else:
            #print(i)
            num+=roman[s[i]]
            i+=1
      return num
ob1 = Solution()

message = str(input("Please enter your roman number: "))
if message <= ("MMMCMXCIX"):
   print (ob1.romanToInt(message))
else:
    print ("Try again")

J'ai mis la condition qui est, si le nombre romain d'entrée est égal ou inférieur à MMMCMXCIX , il imprimera le nombre romain; sinon, il imprimera Try again .

Le problème est que lorsque j'entre X , V ou lié à la valeur X et V , la sortie affiche Try again

S'il vous plaît, aidez-moi à comprendre où je me suis trompé.


2 commentaires

Que doit faire cette ligne if message <= ("MMMCMXCIX") ? Il compare l'entrée utilisateur à une chaîne. N'avez-vous pas besoin de convertir les deux en nombres entiers avant de les comparer?


if message <= ("MMMCMXCIX"): Cette ligne compare des chaînes, ce qui signifie que vous comparez le premier caractère du message avec le premier caractère de "MMMCMXCIX" donc tout premier caractère du message qui est après M dans l'alphabet provoquera " Réessayer "pour être imprimé


6 Réponses :


1
votes

C'est parce que vous comparez les chaînes au lieu de cela, convertissez d'abord le roman en int plutôt que de vérifier

class Solution(object):
   def romanToInt(self, s):
      """
      :type s: str
      :rtype: int
      """
      roman = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000,'IV':4,'IX':9,'XL':40,'XC':90,'CD':400,'CM':900}
      i = 0
      num = 0
      while i < len(s):
         if i+1<len(s) and s[i:i+2] in roman:
            num+=roman[s[i:i+2]]
            i+=2
         else:
            #print(i)
            num+=roman[s[i]]
            i+=1
      return num
ob1 = Solution()

message = str(input("Please enter your roman number: "))
# converting to integer than comparing the value of "MMMCMXCIX"
if ob1.romanToInt(message) <= 8999:
   print (ob1.romanToInt(message))
else:
    print ("Try again")


0 commentaires

0
votes

Comme mentionné dans les commentaires, le problème était dû au fait que vous avez comparé la chaîne plutôt que de la première transformation en int, puis de la comparaison.

Une autre approche que vous pouvez essayer est:

def romanToInt(s):
  d = {'m': 1000, 'd': 500, 'c': 100, 'l': 50, 'x': 10, 'v': 5, 'i': 1}
  n = [d[i] for i in s.lower() if i in d]
  return sum([i if i>=n[min(j+1, len(n)-1)] else -i for j,i in enumerate(n)])

print(romanToInt('X')) # 10
print(romanToInt('V')) # 5
print(romanToInt('IV')) # 4
print(romanToInt('XV')) # 15

À mon avis, les deux sont plus pythoniques.


0 commentaires

0
votes

En fin de compte, c'est juste une addition de nombres, il vous suffit de déterminer s'ils doivent être interprétés positivement ou négativement:

True
True
True
True

Production:

roman = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000,'IV':4,'IX':9,'XL':40,'XC':90,'CD':400,'CM':900}

def roman2Dec(inp):
    inpNum = [roman[x] for x in inp]
    return sum([-x if i < len(inpNum)-1 and x < inpNum[i+1] else x for i, x in enumerate(inpNum)])

for nums in [('IX', 9), ('XL', 40), ('LXI', 61), ('MMMCMXCIX', 3999)]:
    result = roman2Dec(nums[0])
    print result == nums[1]


0 commentaires

0
votes

Vous trouverez ci-dessous quelques approches ci-dessous avec leurs temps d'exécution respectifs pour convertir les chiffres romains en nombres entiers.

Solution 1: (Autonomie approximative = 52 ms)

def romanToInt(self, s: str) -> int:
 s = s.upper()
 roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
 num = 0

 for i in range(len(s)-1):
    if roman[s[i]] < roman[s[i+1]]:
        num += roman[s[i]]*-1
        continue

     num += roman[s[i]]

  num +=roman[s[-1]]

  return num

Solution 2: (Autonomie approximative = 60 ms)

def romanToInt(self, s: str) -> int:
 s = s.upper()
 roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
 num = 0

 s = s.replace("IV", "IIII").replace("IX", "VIIII")
 s = s.replace("XL", "XXXX").replace("XC", "LXXXX")
 s = s.replace("CD", "CCCC").replace("CM", "DCCCC")

 for x in s:
    num += roman[x]

 return num

Solution 3: (Autonomie approximative = 48 ms)

def romanToInt(self, s: str) -> int:
 s = s.upper()
 roman = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 }    
 num = 0

 for i in range(len(s)):

    if i!= len(s)-1 and roman[s[i]] < roman[s[i+1]]:
         num += roman[s[i]]*-1
    else:
         num += roman[s[i]]

  return num

La solution la plus simple semble parfois être la meilleure :)


0 commentaires

0
votes

Vous pouvez résoudre cette question de manière simple comme ci-dessous.

Cette question peut être résolue avec l'idée que chaque chiffre romain dans le nombre romain est arrangé dans l'ordre décroissant si ce n'est pas le cas alors c'est un cas spécial comme 'IV', 'IX', 'XL', .....

Dans ce qui suit, le cas particulier ci-dessus est traité par l'instruction if .

def romanToInt(s):
    mapping  = {
        'I': 1,
        'V': 5,
        'X': 10,
        'L': 50,
        'C': 100,
        'D': 500,
        'M': 1000,
        }
        
    min_ = None
    total = 0
    for c in s:
        val = mapping[c]
        print(val)
        if min_ and val > min_:
            total -= min_*2
        else:
            min_ = val
        total += val
                
    return total


0 commentaires

0
votes
def romanToInt(s):    
    p=z=0
    for i in map('IVXLCDM'.find,s[::-1]):x=[1,5][i%2]*10**(i//2);z+=[x,-x][p>x];p=x
    return z

0 commentaires