I've been stuck on Vigenere in pset6 for a few days now, and I've finally got it. It somehow took me longer to do Vigenere in Python than in C, interestingly. But, I'm confused about one thing: why do I need the "% 32 -1" in the "else" part of the "for" loop (it works, but I don't intuitively understand why). Note that in this Vigenere function, the key inputted in the main() function I use (and haven't shown here) is sys.argv[1] and so I think the reason will be due to the fact that inputted a keyword of "baz" will provide a different shift than "BaZ" if the "% 32 - 1" is not included. Originally, I had just used " - 97" after inputting sys.argv[1].lower() into the Vigenere function, but that messed up the program since it converted the keyword from being stored as a list to being stored as a string, which precludes manipulation via "counter % n". But that's a tangent--my main confusion lies in the fact that using "%32 - 1" makes the case-sensitivity of the function work, and I don't understand why?! (Yes, I know 32 is the difference between lower and upper case characters--so what?)

def vigenere(key, textToEncrypt):
    counter = 0
    ciphertext = ""
    n = len(key)

    for char in textToEncrypt:
        if not char.isalpha():
            ciphertext += char
            newChar = ord(char) + (ord(key[counter % n]) % 32 - 1 )
            if (char.isupper() and newChar > 90) or newChar > 122:
                newChar -= 26
            ciphertext += chr(newChar)
            counter += 1
    return ciphertext

1 Answer 1


It works because the ASCII table is structured that way. "A" has an ASCII value of 65, or 2*32+1, "Z" has an ASCII value of 90, or 2*32+26, lower-case letters use 3*32 instead, but same numbers behind. The bit of value 32 determines the case. That's true even for large ranges of other encodings like Unicode.

I don't see how .lower() would not work, and you pass a string anyway, so I also don't understand your argument of list vs. string. The only problem with index access on strings is when you want to change them, reading is totally fine. So you could use index access on key, whether sys.argv[1] or sys.argv[1].lower(), but not on ciphertext, which you want to write to.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .