Fundamentals of Data Science: Vigenere Cipher Project

I’m running into issues with this code:

alphabet = ‘abcdefghijklmnopqrstuvwxyz’
dictionary = {}
reverse_dictionary = {}

for i in range(0, len(alphabet)):
dictionary[i] = alphabet[i]

reverse_dictionary = {value: key for key, value in dictionary.items()}

def vigenere_cipher(keyword, encoded_message):
keyword_phrase = ‘’
decoded_message = ‘’
for i, char in enumerate(encoded_message):
if char.isalpha():
x = keyword[i % len(keyword)]
keyword_phrase += x
else:
keyword_phrase += char
for x, y in zip(encoded_message, keyword_phrase):
if x.isalpha():
decode_index = (alphabet.index(x) + reverse_dictionary[y]) % len(alphabet)
decoded_message += alphabet[decode_index]
else:
decoded_message += alphabet[decode_index]
return decoded_message

vigenere_cipher(‘dog’, ‘ymlok’)

I’m trying to get it to output ‘barry’ but it outputs ‘bbabarbarrbarry’ instead. I’m stuck how do I fix it?
Thanks in advance.

The problem seems to be that you have one for-loop inside of the other one.
You can change the indentation of that second for-loop so that is no longer the case.

Also, next time, please use the </> button and put your code on lines between the ``` and ```
so that your code keeps its formatting (spaces, indents, and so on).

3 Likes

Thanks, that worked (partially, the decryption still messes up after a space or special character in a phrase).

I’ll remember to add the </> next time, I didn’t know that.

In the second for-loop, in the else block,
you had

      decoded_message += alphabet[decode_index]

but you are doing this when x.isalpha() is False,
meaning that x would hold a space or other special character,
so you should be adding this character to the string without modifying it.

So … that line should be

      decoded_message += x
3 Likes

Thanks! When I call it with that change, it does this:

<“”"
vigenere_cipher(‘dog’, ‘ymlok cp’) #output '‘barryofd’
“”">

instead of the desired “barry is”, thus breaking the decryption.

It’s a head scratcher, any other ideas?

I think the problem is the enumerate in  
for i, char in enumerate(encoded_message):  
This increases the value of i, which is used to find the index of the character used from the keyword in your code.
The enumerate increments the value of i for each iteration of the loop;
but you only want i to increase when char is a letter, and not when i is a space or something else.
(Here, “increment i” means “increase i by 1”.)

You can fix that by setting up i outside the loop, and incrementing i inside the if-block and changing that for to be  
for char in encoded message:  

alphabet = 'abcdefghijklmnopqrstuvwxyz' dictionary = {} reverse_dictionary = {} for i in range(0, len(alphabet)): dictionary[i] = alphabet[i] reverse_dictionary = {value: key for key, value in dictionary.items()} def vigenere_cipher(keyword, encoded_message): keyword_phrase = '' decoded_message = '' i = 0 for char in encoded_message: if char.isalpha(): x = keyword[i % len(keyword)] keyword_phrase += x i += 1 else: keyword_phrase += char for x, y in zip(encoded_message, keyword_phrase): if x.isalpha(): decode_index = (alphabet.index(x) + reverse_dictionary[y]) % len(alphabet) decoded_message += alphabet[decode_index] else: decoded_message += x return decoded_message result = vigenere_cipher('dog', 'ymlok cp') print(result)
1 Like

That worked. Thanks.