ZachHofmeister
ZachHofmeister

Reputation: 173

Python IndexError: list index out of range with long string

My code seems to work with shorter strings, but inexplicably to me gets stuck on others. The function of this is to replace characters with digits, and I have it print out the new string after each part is replaced. Any help you can give me is appreciated, thanks!

By the way, I did look at the similar questions on this and they did not answer my particular question, please don't remove my question.

possibleChars = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W',
'X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','1','2','3','4','5','6','7','8','9','0',' ',',','.','?','!','/','\\','[',']','{','}',
'|','<','>',';',':','+','=','-','_','(',')','@','#','$','%','^','&','*','~','`']  #0-92

possibleCharsToDigit = ['1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3',
'4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8',
'9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3',
'4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3'] #0-92

password = "How is your day today?"

def passwordToDigit(passToConvert):
    passLen = len(passToConvert) #puts the length of the password in a variable
    i = 0 #i is the selected character in the password
    j = 0 #j is the selected possible char, i.e. '0' is 'A' in possibleChars or '1' in possibleCharsToDigit
    while i < passLen:
        if passToConvert[i] == possibleChars[j]:
            passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
            i += 1
            print passToConvert
        else:
            j += 1
    print passToConvert

passwordToDigit(password)

Upvotes: 0

Views: 244

Answers (4)

Gavin
Gavin

Reputation: 1123

As you increment j within your while loop, without ever resetting it, each time you successfully match a character and move onto the next one. This will cause your code to fail as soon as you have a character earlier in possibleChars than a previous one.

To illustrate:

passwordToDigit('ABCDEFGHIJKLMNOP')  #will work correctly
passwordToDigit('BA') #will fail with IndexError

Quick Solution

The quickest solution would be to reset the j index when you find a match.

ie

# ...
if passToConvert[i] == possibleChars[j]:
    passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
    i += 1
    print passToConvert
    j = 0  #Reset tje j index to start searching from beginning
else: 
#...

Dict Solution

You could also spend some time refactoring your code to use a dict to map characters to digits as in:

import string
charopts = string.ascii_uppercase + string.ascii_lowercase + string.digits[1:] + r'0 ,.?!/\[]{}|<>;:+=-_()@#$%^&*~`'
char2dig = dict((k,str((i+1)%10)) for i,k in enumerate(charopts))

def passwordToDigitDic(passToConvert):
    newpass = '' 
    for c in passToConvert:
        newpass += char2dig[c]
        print(newpass + passToConvert[len(newpass):])

passwordToDigitDic('ABCDEFGH')
passwordToDigitDic('HGEFBCA')

Note, if you are ever interested in doing the translation in one go as opposed to step by step with prints, look into the string.translate function.

Upvotes: 1

CK.Nguyen
CK.Nguyen

Reputation: 1368

you should set j = 0 in the if passToConvert[i] == possibleChars[j] clause:

def passwordToDigit(passToConvert):
    passLen = len(passToConvert) #puts the length of the password in a variable
    i = 0 #i is the selected character in the password
    j = 0 #j is the selected possible char, i.e. '0' is 'A' in possibleChars or '1' in possibleCharsToDigit
    while i < passLen:
        if passToConvert[i] == possibleChars[j]:
            passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
            i += 1
            j = 0
            print passToConvert
        else:
            j += 1
    print passToConvert

Upvotes: 1

bharat batra
bharat batra

Reputation: 11

When i=passLen-1, then you are trying to access passToConvert[i+1], which is out of the range of passToConvert. Hence you are getting this error. Try this:

 if passToConvert[i] == possibleChars[j]:
   if i<passLen-1:
        passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
   else: 
        passToConvert = passToConvert[0:i] + possibleCharsToDigit[j]
   i += 1
   print passToConvert

Upvotes: 0

pkacprzak
pkacprzak

Reputation: 5617

When you are incrementing j variable inside the while loop, notice that when j gets bigger than the length of possibleCharsToDigit list then you are trying to access its element with index out of bounds.

Upvotes: 2

Related Questions