Yoruke
Yoruke

Reputation: 15

Trying to wrap caesar cypher (Python)

I've tried using "if" statements to skip characters that aren't alphabetical but It keeps ignoring the code and adding the shifted characters. I'm trying to shift the user input by 2 but the encoded-word should not have any special characters so the shift would wrap round back from z-a.

The code below is before I tried "if" statements.

encoded_word = ("")
decoded_word = ("")

def Encoding(text):
    global encoded_word
    letter_list = list(text)
    length_list = len(text) 
    for i in range (0,length_list):
        letter_ord = ord(letter_list[i])
        encoded_letter = chr(letter_ord+2)
        encoded_word = (encoded_word + encoded_letter)
    print ("The encoded word is now:",encoded_word)

def Decoding(text):
    global decoded_word
    letter_list = list(text)
    length_list = len(text) 
    for i in range (0,length_list):
        letter_ord = ord(letter_list[i])
        decoded_letter = chr(letter_ord-2)
        decoded_word = (decoded_word + decoded_letter)
    print ("The decoded word is:",decoded_word)

decode_encode = str(input("Would you like to encode or decode text? encode/decode: "))
if decode_encode == "encode":
    user_word = str(input("Enter in a word to encode: "))
    Encoding(user_word)
if decode_encode == "decode":
    user_word = str(input("Enter in the encoded word: "))
    Decoding(user_word)

Upvotes: 1

Views: 70

Answers (4)

Sash Sinha
Sash Sinha

Reputation: 22473

I think you are on the right track you just to deal with a couple more edge cases such as if the shift amount is greater than 26, or if the shift needs to wrap around, etc. Additionally, string concatenation using + is inefficient since a copy of the existing string needs to be made each concatenation. Therefore, consider appending to a list of characters instead and only creating an output encoded/decoded string at the end:

SHIFT_AMOUNT = 2

def encode(text):
    res = []
    actual_shift_amount = SHIFT_AMOUNT % 26
    for ch in text:
        new_letter = ch
        if ord('a') <= ord(ch) <= ord('z'):
            if (ord(ch) + actual_shift_amount) <= ord('z'):
                new_letter = chr(ord(ch) + actual_shift_amount)
            else:
                new_letter = chr(ord('a') + actual_shift_amount - (ord('z') - ord(ch) + 1))
        elif ord('A') <= ord(ch) <= ord('Z'):
            if (ord(ch) + actual_shift_amount) <= ord('Z'):
                new_letter = chr(ord(ch) + actual_shift_amount)
            else:
                new_letter = chr(ord('A') + actual_shift_amount - (ord('Z') - ord(ch) + 1))
        res.append(new_letter)
    return ''.join(res)

def decode(text):
    res = []
    actual_shift_amount = SHIFT_AMOUNT % 26
    for ch in text:
        new_letter = ch
        if ord('a') <= ord(ch) <= ord('z'):
            if (ord(ch) - actual_shift_amount) >= ord('a'):
                new_letter = chr(ord(ch) - actual_shift_amount)
            else:
                new_letter = chr(ord('z') - actual_shift_amount + (ord(ch) - ord('a') + 1))
        elif ord('A') <= ord(ch) <= ord('Z'):
            if (ord(ch) - actual_shift_amount) >= ord('A'):
                new_letter = chr(ord(ch) - actual_shift_amount)
            else:
                new_letter = chr(ord('Z') - actual_shift_amount + (ord(ch) - ord('A') + 1))
        res.append(new_letter)
    return ''.join(res)


decode_or_encode = input("Would you like to encode or decode text? encode/decode: ").lower()
if decode_or_encode == "encode":
    user_word = input("Enter in a word to encode: ")
    print(encode(user_word))
elif decode_or_encode == "decode":
    user_word = input("Enter in the encoded word: ")
    print(decode(user_word))

Example Usage encode:

Would you like to encode or decode text? encode/decode: encode
Enter in a word to encode: Yoruke-Stack-Overflow
Aqtwmg-Uvcem-Qxgthnqy

Example Usage decode:

Would you like to encode or decode text? encode/decode: decode
Enter in the encoded word: Aqtwmg-Uvcem-Qxgthnqy
Yoruke-Stack-Overflow

Try it here.

Upvotes: 0

Shovra
Shovra

Reputation: 76

The approach you are following is not the best one. However, assuming that you are considering lowercase characters only.

Encoding

replacing

encoded_letter = chr(letter_ord + 2)

with

encoded_ord = letter_ord + 2
if encoded_ord > ord('z'):  # after encoding if exceeds from 'z'
    difference = encoded_ord - ord('z')  # finding how much exceeded from 'z'
    encoded_ord = ord('a') + difference + 1  # restart from 'a' again.
encoded_letter = chr(encoded_ord)

Decoding

replacing

decoded_letter = chr(letter_ord-2)

with

decoded_ord = letter_ord - 2        
if decoded_ord < ord('a'):     # after decoding if deceeds from 'a'
    difference = ord('a') - decoded_ord   # finding how much deceeded from 'a'
    decoded_ord = ord('z') - difference + 1   # restart from 'z' again but backward
decoded_letter = chr(decoded_ord)

should work

Upvotes: 0

Andrei
Andrei

Reputation: 5

The problem is that when adding or subtracting 2 you do not check if you reached the limit of the alphabet ('a' or 'z'). You should do something like

if encoded_letter > "z":
   # do something

Upvotes: 0

Kevin S.
Kevin S.

Reputation: 29

to check if a character is a letter you can use isalpha(). For example should print just d and f:

    list = ["3","2","-","1","4","5","-","3","d", "f"]
    character_list = []

    for i in list:
        if i.isalpha():
            character_list.append(i)
        
    print (character_list)

Upvotes: 1

Related Questions