Caesar Cipher Python

python

#1

So I've been working on a Caesar Cipher in python ever since @stetim94 mentioned it in my old challenges topic 22 days ago.
I gave up on it for a while so that I could just think about it rationally and figure it out, but my weekend has started, and I think that I'm ready to finish it. The only thing is that I have so much going on inside of it, that I need somebody who has a fresh mind on this to kind of help me out with what I'm having trouble with.
The program I want to build is one that takes user input and encrypts and decrypts based on what the user chooses. I haven't even started the decryption yet, because I'm having trouble with the encryption, but I should be able to figure out the subtract fairly easily.
I want the user to enter a shift as well, and I want up to three numbers to be entered, so if the shift was '123', and the text was 'zzz' it would return 'abc', basically I want to be able to have a key that shifts in a pattern.
This sounds easy enough, and I have been trying for a week or so, but I'm stuck right now. Not even regarding the logic of my program right now, I'm not even outputting the correct thing.
The other half of the issue is that I don't know how to condense the pattern into a loop, and that's probably the worst part of it all, because I'm drawing a major blank on where to start.

So here is my code. I know it's not very good, so no laughing :slight_smile: , just wondering if anybody has insight to share because this is kind of my weekend project.

choice = raw_input("Would you like to 'encrypt' or 'depcrypt'(Type e or d or QUIT to quit): ")
bad = " .,!?;"
while choice != "QUIT":
   if choice == "e":
      text = raw_input("Enter text: ")
      shift = raw_input("Enter shift (numbers, up to a pattern of 3): ")
      encodedStr = ""
      if len(shift) == 1:
         for letter in text.lower():
            if letter not in bad:
               if (ord(letter) + int(shift) < 122):
                  letter = chr(ord(letter) + int(shift))
               else:
                  i = 0
                  num = int(shift)
                  while (ord(letter) + i <= 122): 
                     num -= 1
                     i += 1
                  letter = chr(97 + num)
            encodedStr += letter
         print encodedStr
      elif len(shift) in range(4):
         shifts = []
         for character in shift:
            shifts.append(int(character))
         for letter in text.lower():
            for counter in range(1, len(text), 1):
               for increase in range(1, len(shift), 1):
                  if letter not in bad:
                     if (ord(letter) + shifts[increase] < 122):
                        letter = chr(ord(letter) + shifts[increase])
                     else:
                        i = 0
                        num = shifts[increase]
                        while (ord(letter) + i <= 122):
                           num -= 1
                           i += 1
                        letter = chr(97 + num)
                  encodedStr += letter
         print encodedStr
      else:
         print "Just up to three numbers, please."
   elif choice == "d":
      text = raw_input("Enter text: ")
      shift = raw_input("Enter shift (numbers, up to a pattern of 3): ")
      encodedStr = ""
      if len(shift) == 1:
         for letter in text.lower():
            if letter not in bad:
               if (ord(letter) - int(shift) >= 97):
                  letter = chr(ord(letter) - int(shift))
               else:
                  i = 0
                  num = int(shift)
                  while (ord(letter) - i >= 97): 
                     num -= 1
                     i += 1
                  letter = chr(122 - num)
            encodedStr += letter
         print encodedStr
   else:
      print "That's not a valid choice!"
   choice = raw_input("Would you like to 'encrypt' or 'depcrypt'(Type e or d or QUIT to quit): ")
print "Cryptation complete!"

EDIT: Updated my code, added some stuff, (decryption of a static shift tried to figure out the loop), but I'm still having a heck of a time so any advice on the loop would be spectacular.


#2

Nicely done!

I did one of these a while back. If you're interested in how I did it...

#Caesar Cipher Program

while True:
    def helper(message, shift):
        message = message.lower()
        secret = ""
        for c in message:
            if c in "abcdefghijklmnopqrstuvwxyz":
                num = ord(c)
                num += shift
                if num > ord("z"):
                    num-=26
                elif num < ord("a"):
                    num+= 26
                secret = secret +chr(num)
            else:
                secret = secret + c
        return secret

    def encrypt(message):
        return helper(message, 3)

    def decrypt(message):
        return helper(message, -3)

    msg = input("Message to Encode:  ")
    if len(msg)>0:
        secret = encrypt(msg)
        print("The encoded message is:",secret)
    else:
        secret = input("Message to Decode: ")
        if len(secret) > 0:
            msg = decrypt(secret)
            print("The decoded message is:",msg)

Feel free to use my code for an answer to your mystery, but your code looks great so far.


#3

aha, thanks, but it's a disaster.
I got the easy part done. Like it works perfectly if you just do one shift, (i also was able to add in the decrypt part about an hour ago), but my big problem is figuring out how to write a loop for the shift pattern, if somebody wants the shift to be more than just a static number all the way across.
I want to ask where you learned about ord() though.
Python is one of the things that I felt like I knew really well, but I HAD NO IDEA HOW TO CAST A SYMBOL AS AN ASCII NUMBER AND I WAS SO MAD! It took me like two hours to find it on stack overflow smh.
But thank you for your code! It looks really good.


#4

Just read your code, I actually tried to do this a while back and got into so much that rn all I'm working on is cryptography. What you are working on is sort of like a Vigneré Cipher but with no keyword, (google it lol) :sweat_smile:. But to do what you are trying to do you must take into account that user text input is always a string and to change the shift of individual letters by a specific key I would suggest either converting it to list first because modifying lists is much easier, or using the .split() method and then the .join() method.


#5

See how your indentation runs off to the right? There's so much nesting going on you won't be able to keep it all in your head at once.

So you need to extend the key to be as long as the message, then loop through pairs of keys for each character and each character in the message.. and let some other function do the shifting:

Create a function that shifts a single character.

Create a function that iterates over characters in the message and the key.

Use itertools.cycle to repeat the key.

itertools.cycle(map(int, '123')) # 1, 2, 3, 1, 2, 3, 1, ...

Use zip to iterate through the cycled key and the message

for a, b in zip('purple', 'ketchup'):
    # p, k
    # u, e
    # r, t
    # ...

string.ascii_lowercase can be used to get a sequence that counts up from 'a' with indexing starting at zero.

Generally you want any part in your code to be simple enough to understand as a whole, if it needs to do multiple things then let other functions worry about it.


#6

Alright, this really helps a lot, and it clears some things up a bit.
I'm going to think about this more and how to change the things correctly, just to dig deeper before I attempt this.
I knew the nesting was a problem, but I couldn't think of a way around it.
Thanks for looking into my code and for the feedback.
Creating the functions is a really smart thing to do, and honestly I don't use them as much as I should, so that's an easier way to put things in certain parts and not just have this long run on code that tries to do everything at once.
I've never seen itertools.cycle before, but that's a huge help, and that will definitely make everything go much more smoothly, because then I wouldn't have to worry about how long the shift is that the user wants to create.
I'll be working on this, it might take me a while before I finish it because I'll probably be messing with it for a little bit, but I'll keep everybody updated. :))


#7

Its a very good program, just you haven't defined raw_data.


#8

A post was split to a new topic: Running python code


#9