Need help resolving incorrect output - Vigenere Cipher

Hello, I’ve been trying to figure out what causes an incorrect output in my program. The output is correct for most of the part, that’s why I couldn’t figure out which part of the code in my program is not working properly…

The Code:

from string import ascii_letters

def get_cipher_text(new_shift, character):

    if character in ascii_letters:
        return ascii_letters[new_shift]
    return character

def check_text_case(symbol, result, index):

    if symbol.isupper():
    elif symbol.islower():

def vigenere_cipher(message, key):

    translated_message = []
    key_index = 0
    for char in message:
        char_position = (ascii_letters.find(char) - ascii_letters.find(key[key_index])) % len(ascii_letters)
        check_text_case(char, translated_message, char_position)

        key_index += 1
        if key_index == len(key):
            key_index = 0
    return ''.join(translated_message)
print(vigenere_cipher("eoxum ov hnh gvb", "dog"))

# Output: barry lh ezb spy
# Expected output: barry is the spy


Fun cipher!

Can you be more specific?

  • What have you tried?
  • How did it fail?
  • Where does this leave your intuition of where the problem lies?

Thanks for the prompt response :smiley: I’ve tried one that works but it failed only when I decided to break up the code and put them into different functions. The problem lies at .find in which it will return -1 index if a character in the message isn’t found in ascii_letters. The thing is, I didn’t want to stuff all the code inside one function, though it’d be a good idea to break it up since I got it working at first.

Original Text:

def vigenere_decrypt(message, key):

    translated_message = []
    key_index = 0
    for char in message:
        char_position = ascii_letters.find(char)
        if char_position != -1:
            char_position -= ascii_letters.find(key[key_index]) 

            char_position %= len(ascii_letters)

            if char.isupper():
            elif char.islower():

            key_index += 1

            if key_index == len(key):
                key_index = 0
    return ''.join(translated_message)

print(vigenere_decrypt("eoxum ov hnh gvb", "dog"))

# Output: barry is the spy

It may help to map this out on paper and trace it as you follow your program around. That way, in every juncture you have “expected” results which you can cross-check by putting print statements.

What I personally find most useful in cipher problems is that they really force me to be organized in my planning and error-checking because otherwise the problems start piling on top of each other.

Understood, but oftentimes I get stuck trying to meet the expected results. For instance, crossing out two results after they’ve met the expected results would sometimes break the first result and return an incorrect result again. So I end up in a loop only to realize I need to stack a few more code to meet the expected results, and then this process just keeps going.

I’ve also managed to remove 2-3 lines of code by creating another function to check the length of key_index, the thing is, if I remove any line in vigenere_translate or any function, the whole program just breaks…

I’ve seen other forum posts using itertools to solve this cypher problem with just a function of less than or 10 lines of code, that was amazing but it was beyond my knowledge. Guess it was that curiosity that had me attempt to reduce the number of code in one function.


By expected result I mean within the logic of the code.
Like, are the conditionals being triggered exactly where you want them to for sure?
Is char_position %= len(ascii_letters) getting you everything you need?

Formatted print statements can go a long way in making this more clear.

Leave no stone unturned, and before you know it you’ll have a better clue!