Off-Platform Project: Coded Correspondence

I will answer this question:

This is basically a one line argument, that:

  • Adds +1 to the pointer for the keyword (the pointer is for the index)
  • checks if the new index is higher than the highest index of the keyword (length -1 because we start with 0)
  • calculates the new index, if it is higher (with the modulo operator)

You could do all steps one by one like this:

letter_pointer += 1
if letter_pointer == len(keyword):
   letter_pointer= 0

This is basically the same, as an index, that reaches he length of the keyword, the modulo (%) function will set it to 0.


keyword = "bob"
letter_pointer = 0

print (keyword[letter_pointer])

the result here would be “b”

keyword = "bob"
letter_pointer = 3

print (keyword[letter_pointer])

this would throw an error, because len(keyword) is = 3 and therefor the highest index is 2 ([0], [1], [2] = 3 indexes)
to avoid this, the modulo function is added, that the index can never be at 3 or more.

keyword = "bob"
letter_pointer = 3

letter_pointer = letter_pointer % len(keyword)

print (keyword[letter_pointer])

this repairs the error, because now in this case we set letter_pointer to 3 % 3 (which is 0, because there is no rest if we calculate 3/3)

why are we increasing the letter pointer (with the +1)?
This is because we circle through the keyword (like in the example at the top with “dog”) to add the value to the message values.
When we reach the last letter at len(keyword) - 1 (because of indexing), we need to start at the beginning again with the next circle.
The modulo function is doing all this in one go.

btw. a nice tweak to the solution given is, to make it more flexible.
The solution can still throw a lot of errors, e.g. if you use capital letters or puntuation that is not captured (e.g. ‘:’, ‘;’ etc.)

You can counter that by defining two alphabets:

alphabet = "abcdefghijklmnopqrstuvwxyz"

you do not even need the punctuations variable, because we just make sure that every letter that is not known will just not be decrypted:

for letter in message_coded:
   if letter in alphabet:
      decode_num = (alphabet.index(letter) - keyword[letter_pointer] + 26) % 26
      decoded_message += alphabet[decode_num]
      letter_pointer = (letter_pointer + 1) % len(keyword) 
   elif letter in alphabet_capital:
      decode_num = (alphabet_capital.index(letter) - keyword[letter_pointer] + 26) % 26
      decoded_message += alphabet_capital[decode_num]
      letter_pointer = (letter_pointer + 1) % len(keyword) 
      decoded += letter

this way you will also ensure, that special characters will not cause errors in the code and are translated back correctly.

Even if you would send a message like this:

There is a big flaw with the coder, that you sent us. It created an error (we tried several times with different people!).
Please check if there are bugs in the program you gave us.
People who tested the program: Charly, Marianne, Elsa, Peter
We just wanted to send this poem:
'The birds are beautiful; are they not? they fly like artists; they fly a lot! Is there more freedom; than a bird in the sky? Fly little bird; fly!'

The official solution would try to use letter_value = alphabet.find(letter) on special characters like ‘(’ and ‘;’ which results in an error, because it is not in alphabet (and also not in punctuation).

If capital letters should not be regarded, you can also just put the whole message in .lower() instead, which will then save one line but still encodes capital letters.

You can test this with the following sentence, I put as the final message into the decoder (keyword is the same as in the solution):

Mvtpb Yaxyip! Uro fswyg zw yig Sgwwsuwvs hfhigtglfl embg? (Wznj eshov gv mzrq etim wrfmwv!) Ei jldq jmi rdum fblru ktfv. Frvl Wvoeegk Dfcv Suajel

I hope this helped you.

Hello sherrattsp,

I did check the project and basically this whole process is just to have the keyword phrase at the same length as the message and with the same interrupts.
They could have written keyword_phrase += ' ', and it would have had the same effect.
The only reason in doing this is, to add one letter to the keyword phrase and push the next keyword letter forward.

messsage = "do as i say and now"
keyword = "master"
#to only have keyword calculation, if there is a letter to encrupt, they used this method to make a keyword_phrase:
keyword phrase = "ma st e rma ste rma"

This solution is correct and follows the give description very closely, but it is more complicated than the one with cycling through the keyword when a letter needs to be encrypted or decrypted.

Okay, what is done here?
We will go line by line:

for message_letter, key_letter in zip(lower_message, keyword_phrase):

this line created 2 lists (massage_letter and key_letter) and fills it with a list of single letters of lower_message and keyword_phrase.

zip: created a list with packages of lower_massage and keyword_phase letters [l,k] (l being lower_massage, k being keyword_phrase).

Example (with keyword dog that was made into a keyword phrase like explained above):

lower_message = "i see"
keyword_phrase = "d ogd "
my_list = zip(lower_message, keyword_phrase)

Result would be: [('i', 'd'), (' '. ' '), ('s', 'o'), ('e', 'g'), ('e', 'd')]

at the same time, itassigns the respective volumes to the different lists, so the index 0 of each package to message_letter, the index 1 to key_letter.

for message_letter, key_letter in zip(lower_message, keyword_phrase):
print (message_letter)
print (key_letter)

Result would be:
[‘i’, ’ ', ‘s’, ‘e’, ‘e’]
[‘d’. ’ '. ‘o’, ‘g’, ‘d’]

with the for it now goes through the while list to calculate the index value.

The next 2 lines basically do the same, just one with the message_letter list and the other one with the key_letter list.
They do the calculation on the index of alphabet, that represents the letter.

alpha_index = alphabet.find(message_letter)
key_index = alphabet.find(key_letter)

If the letter of this index is not in the alphabet (e.g. with ’ '), it will return -1. Else it will put the index (e.g. for ‘i’ it will be 8) unti the variables (alpha_index and key_index respective).

The next line basically just checks if the letter was in alphabet or not (-1 means it was not in):

if alpha_index == -1:
            cipher_message += message_letter

So if the alpha_index (of the message) has no letter at this position, the cipher_message (decoded or encoded) will just put the same letter there instead of calculating a new value.

Even though there are easier ways to get to the result, this is a great example of using a lot of different methods in a creative way (e.g. zip). In regards to learning the phyton techniques, this is a very good solution.

I hope I was able to help you with this explanation.