Matthew Willis
Matthew Willis

Reputation: 47

Python Caesar cipher decoding

I am new to Python and decided to make my own Caesar cipher encryptor. I've made the encrypter and it is ok, however, the decrypter can only successfully decrypt one word. If I enter a sentence, it merges the decryption all together. Is there an easy fix for this?

def decrypt():
    ciphertext = raw_input('Please enter your Encrypted sentence here:')
    shift = input('Please enter its shift value: ')
    space = []

    cipher_ords = [ord(x) for x in ciphertext]
    plaintext_ords = [o - shift for o in cipher_ords]
    plaintext_chars = [chr(i) for i in plaintext_ords]
    plaintext = ''.join(plaintext_chars)
    print 'Decryption Successful'
    print "" 
    print 'Your encrypted sentence is:', plaintext

decrypt()

Upvotes: 2

Views: 16450

Answers (3)

MarianD
MarianD

Reputation: 14141

Your probably wanted not to decrypt the space character as in your "encrypted" text it is not encrypted. If this is the case, here is the modified part of your code:

cipher_ords     = [ord(x)    if x != " " else -1  for x in ciphertext]
plaintext_ords  = [o - shift if o != -1  else -1  for o in cipher_ords]
plaintext_chars = [chr(i)    if i != -1  else " " for i in plaintext_ords]

(Let cipher_ords has -1 for each space symbol and consequenlty in plaintext_ords, too. In plaintext_chars this -1 will return back to the original space symbol.)

Upvotes: 1

Chris
Chris

Reputation: 22953

What I propose is to split your raw_input() at every space, iterate over each word in the split input, and then join the sentence back together with spaces. It seems to be the most canonical solution I could think of:

def decrypt():
    ciphertext = raw_input('Please enter your Encrypted sentence here:')
    shift = int(raw_input('Please enter its shift value: '))
    space = []

    # creat a list of encrypted words.
    ciphertext = ciphertext.split()

    # creat a list to hold decrypted words.
    sentence = []

    for word in ciphertext:
        cipher_ords = [ord(x) for x in word]
        plaintext_ords = [o - shift for o in cipher_ords]
        plaintext_chars = [chr(i) for i in plaintext_ords]
        plaintext = ''.join(plaintext_chars)
        sentence.append(plaintext)

    # join each word in the sentence list back together by a space.
    sentence = ' '.join(sentence)
    print 'Decryption Successful\n'
    print 'Your encrypted sentence is:', sentence

decrypt()

Output:

Please enter your Encrypted sentence here: lipps xlivi
Please enter its shift value:  4
Decryption Successful

Your encrypted sentence is: hello there

Notes:

  • Never just do input() in Python 2.x because it uses eval() implicitly - which can be very dangerous. Use int(raw_input()) instead.
  • I removed the extra print statement you had to create a new line. Append a new line to your second print statement instead.

Upvotes: 1

brianpck
brianpck

Reputation: 8254

Based on your comment about "hello there" as input, I suspect that the issue has to do with unprintable ascii characters. You are missing two crucial parts of your Caesar cypher.

For the first issue, consider:

>>> chr(ord(' ') - 4)
'\x1c'

Oh no! 4 characters to the left of the space (32) is the...ASCII file separator! How did Caesar fit that on a clay tablet?

For the second issue:

>>> chr(ord('A') - 4)
'='

The 'A' should wrap around in a true Caesar cypher, but instead you are exploring the hinterlands (well, not really) of non-alphabetic ASCII codes.

You thus need to include two important steps:

  1. Exclude non-alphabetic characters from the Caesar cypher.
  2. Make sure that letters wrap when approach the end: A - 1 should equal Z.

Upvotes: 1

Related Questions