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