Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Decode function on caesar cypher is weird when using modulo

I’m currently making a caesar function and in the process of optimization, ran across a really weird problem when decrypting an encoded text. For example, encoding civilization with a shift value = 5 results in the output "hnanqnefynts", however upon decoding it results in "csvslszktsox", notice that the odd positions in the word decode correctly, while the even positions are instead shifted by 10, e.g: i -> s, a -> k, n -> x.

I believe the main bug from the code comes from using an if statement to make the shift value negative instead of a minus operator and how it works with the modulo operator, although I don’t quite understand why only the even positions in the resulting word is affected.

def caesar(plain_text, shift_amount, cipher_direction):
    text_to_list = list(text)
    output = ''
    operation = 'encoded'
    for letter in text_to_list:
        letter_int = alphabet.index(letter)
        if cipher_direction == 'decode':
            shift_amount *= -1
            operation = 'decoded'
        processed_letter = alphabet[(letter_int + shift_amount) % len(alphabet)]
        output += processed_letter

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Running this function gives NameError: name 'text' is not defined. I assume you meant text_to_list = list(plain_text).

As for your main problem, the odd/even issue, it’s because you put shift_amount *= -1 inside your for loop. This causes shift_amount to change sign on alternating decode operations. You only need to check the encode/decode flag once, so move it outside the loop.

Also, you’ve got two variables whose value isn’t used anywhere: output and operation. I assume that output is meant to be the return value of the function, so you need to actually return it. But operation is just a redundant near-copy of cipher_direction, so just get rid of it.

Here’s a fixed version:

alphabet = 'abcdefghijklmnopqrstuvwxyz'

def caesar(plain_text, shift_amount, cipher_direction):
    text_to_list = list(plain_text)
    output = ''
    if cipher_direction == 'decode':
        shift_amount *= -1
    for letter in text_to_list:
        letter_int = alphabet.index(letter)
        processed_letter = alphabet[(letter_int + shift_amount) % len(alphabet)]
        output += processed_letter
    return output

Sample input and output:

>>> caesar('civilization', 10, 'encode')
'msfsvsjkdsyx'
>>> caesar('msfsvsjkdsyx', 10, 'decode')
'civilization'
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading