0

I'm trying to use a 2d grid cipher to encrypt a string in Python, but my nested loops are causing out of range errors.

Here's my code:

def encrypt():
    before = str(input("Type a string to encrypt: "))
    columns = int(input("How many table columns would you like: "))
    split = [before[i:i+columns] for i in range(0, len(before), columns)]
    rows = len(split)
    after = []
    for i in range(0, columns):
        for j in range(0,rows):
            after.append(split[j][i])
    print(after)

And here's the error I am receiving:

Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    encrypt()
  File "E:/Python/cipher.py", line 12, in encrypt
    after.append(split[j][i])
IndexError: string index out of range
4
  • range(n) is the same as range(0, n). the 0 is implicit Commented Jan 30, 2015 at 22:19
  • Hav you tried swapping the indexes? With i you iterate over the columns and with j over each substring. So you should use them for that. Commented Jan 30, 2015 at 22:21
  • Have you inspected your array to see if its elements are the length you expect? Commented Jan 30, 2015 at 22:22
  • @tdelaney I have, and they are Commented Jan 30, 2015 at 22:30

3 Answers 3

1

The problem occurs because your input string is not guaranteed to be a multiple of the rows. For example, using 3 columns "Input String to Encrypt" fails to encrypt because it produces a split list of ['Inp', 'ut ', 'Str', 'ing', ' to', ' En', 'cry', 'pt']. Notice the last element in the array only has 2 elements.

If you pad your input string with a space like: "Input String to Encrypt " The encryption works as the split produces: ['Inp', 'ut ', 'Str', 'ing', ' to', ' En', 'cry', 'pt ']

Sign up to request clarification or add additional context in comments.

1 Comment

Yes! Thank you. This is a big help!
0

The problem (try printing split) is that all elements in split are not necessarily rows long:

Type a string to encrypt: hello world
How many table columns would you like: 3
['hel', 'lo ', 'wor', 'ld']

You have to decide what you want to do. Maybe append spaces to the end of the last string if it's not long enough.

You might also want to have a look at enumerate. Happy hacking.

Update: Let's say you choose to use 2 columns, and a string length that is divisible by two:

Type a string to encrypt: helo
How many table columns would you like: 2
['he', 'lo']
['h', 'l', 'e', 'o']

Seems to work. Oh, I had to change your code a little because input doesn't do what you think:

def encrypt():
    before = raw_input("Type a string to encrypt: ")
    columns = int(raw_input("How many table columns would you like: "))
    split = [before[i:i+columns] for i in range(0, len(before), columns)]
    rows = len(split)
    after = []
    for i in range(0, columns):
        for j in range(0,rows):
            after.append(split[j][i])
    print(after)

Update 2: If you want to pad the input using spaces, just add this line:

before += " " * (columns - len(before) % columns)

You'll end up with this code:

def encrypt():
    before = raw_input("Type a string to encrypt: ")
    columns = int(raw_input("How many table columns would you like: "))
    before += " " * (columns - len(before) % columns)
    split = [before[i:i+columns] for i in range(0, len(before), columns)]
    rows = len(split)
    after = []
    for i in range(0, columns):
        for j in range(0,rows):
            after.append(split[j][i])
    print ''.join(after)

Example output:

Type a string to encrypt: hello world
How many table columns would you like: 4
hore llwdlo 

2 Comments

That isn't the problem, sorry. Even when the rows are even, I still get the error. EDIT: Apologies, I had i and j mixed up and it turns out that this is the problem. Thank you very much!
works for me, after small modifications (see update)
0

The errors was caused by rows not guaranteed to be regular and the string length not being divisible by the number of columns all the time.

(I don't have enough reputation to post images, sorry)

https://i.sstatic.net/kaJJo.png

The first grid will not work, as there are 4 empty spaces after the second '!' that we cannot access. The second grid will work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.