# Coded Correspondence Question - Vigenere Cypher (i think i am close)

i am trying to create the vigenere cypher and i think i am close but i know i am missing something. this comes from the coded correspondence jupyter notebook project and although i am 63% of the way through the python course here on codecademy, i found this project to be impossible to do and had to look at the solutions, and i still don’t understand the solution for how they did the vigenere cypher.

here is what i have so far:

``````alphabet = "abcdefghijklmnopqrstuvwxyz"
v_message = "txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!"
clue = "fri ends frie nd sfrien dsfri ends frie  nds fri endsfrie ndsfr ien dsfrie nd sfriendsfri "

def vigenere_decode(message, keyword):
vigenere_decoded_message = ""
for c in message:
if c in alphabet:
c_value = alphabet.find(c)
for l in keyword:
if l in clue:
l_value = clue.find(l)
vigenere_decoded_message += [(c_value % 26) + (l_value % len(keyword))]
else:
vigenere_decoded_message += c
return vigenere_decoded_message

print(vigenere_decode("txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!", "friends"))
``````

i am only 2 months in to learning python, never coded anything before, and using no other resources but codecademy and this project blew my mind.

1 Like

Yep, its a tough project to think through.

In your case, you need what’s happening with the keyword to overlap with what’s happening with the letters in message
so you shouldn’t put
`for c in message:`
and
`for l in keyword:`
as separate loops.

Instead of having a loop to go through the message, it may be more useful to have a counter variable [that starts at 0 and increases by 1 each time the letter changes] to then use to find the appropriate thing in the keyword.
And then use something like
`l = keyword[counter_variable % len(keyword)]`
to get the appropriate letter from the `keyword`.

Also, you don’t need `clue` in your function: the `clue` string is just an aid to check that what your doing with the keyword is correct, but it wouldn’t be part of the decoding function. (You don’t need to loop through `clue` at all.)

You’re concerned with the position of the keyword letter `l` in the alphabet, so instead of
`l_value = clue.find(l)`
you should have
`l_value = alphabet.find(l)`

You have:

``````vigenere_decoded_message += [(c_value % 26) + (l_value % len(keyword))]
``````

but you’re adding a letter from `alphabet`, so instead of
`vigenere_decoded_message += [stuff]`
it should be
`vigenere_decoded_message += alphabet[stuff]`
where `stuff` is a placeholder for the calculation to get the index of the appropriate character.

also, the `% 26` should be the last thing done in the calculation (to ensure that you have a valid index of the `alphabet` string).
So you might end up with something like:

``````vigenere_decoded_message += [(c_value + l_value) % 26]
``````

The `else` you have should happen if that letter in the `message` is not in `alphabet`
so
the indentation for
`if c in alphabet:`
and
`else:`
should be the same.

possible solution (try not to look at it until you're done)

Here’s one possible way to do it using much of your code.
The commented out code would print the stuff identical to `hint`.

``````alphabet = "abcdefghijklmnopqrstuvwxyz"
v_message = "txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!"
clue = "fri ends frie nd sfrien dsfri ends frie  nds fri endsfrie ndsfr ien dsfrie nd sfriendsfri "

def vigenere_decode(message, keyword):
vigenere_decoded_message = ""
i = 0 #counter (counts iterations)
for c in message:
if c in alphabet:
c_value = alphabet.find(c)
l = keyword[i % len(keyword)]
#print(l, end="");
l_value = alphabet.find(l)
vigenere_decoded_message += alphabet[(c_value + l_value) % 26]
i += 1
else:
#print(" ", end="")
vigenere_decoded_message += c
#print()
return vigenere_decoded_message

print(vigenere_decode("txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!", "friends"))
``````

Think about the order of the steps for the letters from `keyword` for each letter in the `message`

1. setup (like a counter variable) may be needed
2. get the appropriate letter from `keyword`
3. find the position of that letter in the `alphabet`
4. use that result to get the position of the shifted letter (multiple steps)
1 Like

[quote=“core4207147728, post:1, topic:778129”]

l don’t understand the solution for how they did the vigenere cypher.

Hi, the solution provided works but it is very short and the steps are tough to follow.

Here I have one solution in details. It can be long, but I can read it step-by-step. I’ll walk you through the decoder. Then, I’ll shorten it so that you have another short solution which seems brief.
In the end, I’ll guild you to do the encoder.

Take a look at what we are going to do

``````alphabet = 'abcdefghijklmnopqrstuvwxyz'

message_to_decode = "txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!"
keyword = "friends"

def VigenereC_decoder(message, keyword):
print(message)
# Apply keyword
applied_keyword_phrase = ''
count = 0
for char in message:
if char in alphabet:
applied_keyword_phrase += keyword[count % len(keyword)]
count += 1
#print(count % len(keyword)): 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, ... (repeats)
else:
applied_keyword_phrase += char

print(applied_keyword_phrase)

# List of alphabet_index from Message
print(message)
list_index_message = []

for char in message:
if char in alphabet:
list_index_message += [alphabet.find(char)]
else:
list_index_message += [char]

print (list_index_message)

# List of alphabet_index from Keyword
print(applied_keyword_phrase)
list_index_keyword_phrase = []

for char in applied_keyword_phrase:
if char in alphabet:
list_index_keyword_phrase += [alphabet.find(char)]
else:
list_index_keyword_phrase += [char]

print (list_index_keyword_phrase)

# Result List of alphabet_index += list_index_message[i] + list_index_keyword_phrase[i]
list_index_result = []

for i in range(0, len(list_index_message)):
if type(list_index_message[i]) == int and type(list_index_keyword_phrase[i]) == int:
list_index_result += [list_index_message[i] + list_index_keyword_phrase[i]]
else:
list_index_result += list_index_message[i]

print('result in alphabet_index', '\n', list_index_result)

# convert List_result from alphabet_index to alphabet
list_result = []
else:

print(list_result)

# final result: join list
result = ''.join(list_result)
return result

print(VigenereC_decoder(message_to_decode, keyword))

``````

See my photo for the math of alphabet_index encoding and decoding?

• To decode: alphabet_index_encoded + alphabet_index_keyword
• To encode: alphabet_index_message - alphabet_index_keyword

If step 1 is not clear to follow, let me know.

Oh, and here is the very short solution for the decoder :

``````alphabet = 'abcdefghijklmnopqrstuvwxyz'

message_to_decode = "txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!"
keyword = "friends"

def VigenereC_decoder(message, keyword):
print(message)

# Apply keyword
applied_keyword_phrase = ''
count = 0
for char in message:
if char in alphabet:
applied_keyword_phrase += keyword[count % len(keyword)]
count += 1
else:
applied_keyword_phrase += char

print(applied_keyword_phrase)

# Result
result = ''

for i in range(0, len(applied_keyword_phrase)):
if applied_keyword_phrase[i] in alphabet:
result_index = alphabet.find(message[i]) + alphabet.find(applied_keyword_phrase[i])
result += alphabet[result_index % len(alphabet)]
else:
result += applied_keyword_phrase[i]

return result

print(VigenereC_decoder(message_to_decode, keyword))
``````
1 Like