Sanidhya Sahu
Sanidhya Sahu

Reputation: 37

Roman to int conversion problem gives an string index out of range error

I have a simple task to convert roman to int. this is the code I have been trying.


def romanToInt(s):
    """
    :type s: str
    :rtype: int
    """
    j=0
    print(len(s))
    for i in range(len(s)):
        k=s[i]
        l=i+1
        if s[i]=="I":
            if s[l]=="V":
                j+=4
            elif s[l]=="X":
                j+=9
        elif s[i]=="X":
            if s[l]=="L":
                j+=40
            elif s[l]=="C":
                j+=90
        elif s[i]=="C":
            if s[l]=="D":
                j+=400
            elif s[l]=="M":
                j+=900
        else:
            match k :
                case "I":
                    j+=1
                case "V":
                    j+=5
                case "X":
                    j+=10
                case "L":
                    j+=50
                case "C":
                    j+=100
                case "D":
                    j+=500
                case "M":
                    j+=1000
    return j

a=input("Enter number")
b=romanToInt(a)
print(b)

this code gives this error .

Enter numberIII
3
Traceback (most recent call last):
  File "C:\Users\admin\Desktop\Dekstop Folder\pycharm\python\Leetcode\Roman to int.py", line 46, in <module>
    b=romanToInt(a)
      ^^^^^^^^^^^^^
  File "C:\Users\admin\Desktop\Dekstop Folder\pycharm\python\Leetcode\Roman to int.py", line 13, in romanToInt
    if s[l]=="V":
       ~^^^
IndexError: string index out of range

Process finished with exit code 1

I dont know why it says String index out of range.

I tried printing the length and it is in the range but i dont know why it does not work. please help.

Upvotes: 1

Views: 75

Answers (3)

Corralien
Corralien

Reputation: 120509

It's often better to iterate over elements rather than the index to avoid some IndexError. zip can help you iterate over both the current character and the next one.

Another way to do it:

table = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}

def roman_to_int(s):
    num = 0
    for c1, c2 in zip(s, s[1:]):
        v1, v2 = table[c1], table[c2]
        num += v1 if v1 >= v2 else -v1
    return num + v2  # don't forget to add the last element

Usage:

>>> roman_to_int('IX')
9

>>> roman_to_int('VII')
7

Note: this code doesn't check the validity of the roman numerals (VIIIII = 10)

Upvotes: 2

Selewirre
Selewirre

Reputation: 39

TL;DR: Use the roman.toRoman('XVII') function from the romanpackage, found on pypi, to do this quickly and painlessly.

As suggested in the comment, the 1=i+1 will force the check on the last I to go outside range of the provided string.

Solutions:

  1. The way you are implementing this is very tedious and repetitive. For this reason, I will not try to fix the "index out of range" error with repetitive if statements.

  2. Simply use a python package called roman that does this for you in one line:

       import roman
       a = input("Enter number: ")
       b = roman.toRoman(a)
       print(b)
    

Upvotes: 0

Mark Ransom
Mark Ransom

Reputation: 308500

As mentioned in the comments, your problem comes when i reaches len(s)-1, meaning l=i+1 is one past the end of the string.

Instead of using s[l], you could use a slice of s[l:l+1]. This will return an empty string when l is out of bounds instead of generating an error.

Upvotes: 1

Related Questions