Home > Enterprise >  Decode function on caesar cypher is weird when using modulo
Decode function on caesar cypher is weird when using modulo

Time:07-19

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

CodePudding user response:

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'
  • Related