Home > Net >  Caesar Cipher in Python: remove spaces in a list
Caesar Cipher in Python: remove spaces in a list

Time:03-22

I'm working on a Caesar Cypher project. I take the user's input, turn it into a list, take out spaces, and then encrypt the letters.

My question is: How do I re-add these spaces into the final encrypted message?

Here's what I have achieved so far (pretend word = message)

alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

en_de = input("Do you want to encrypt or decrypt your message? ")
word = input("Enter a word: ")
shift = input("Enter a number: ")

word = list(word)

indexes = []

def encrypt():
  for letters in word:
    if letters in alphabet:
      index = (alphabet.index(letters))
      int(index)
      indexes.append(index)
  print(indexes)
  n = 0
  n = n   int(shift)
  for i in range(len(indexes)):
   indexes[i] = indexes[i]   n
  print(indexes)
  ceaser_cipher = ''
  for i in indexes:
    if i > len(alphabet)-1:
      i %= len(alphabet)
    ceaser_cipher = ceaser_cipher   (alphabet[i])
  for 
  print(ceaser_cipher)

def decrypt():
  for letters in word:
    index = (alphabet.index(letters))
    int(index)
    indexes.append(index)
  print(indexes)
  n = 0
  n = n   int(shift)
  for i in range(len(indexes)):
   indexes[i] = indexes[i] - n
  print(indexes)
  ceaser_cipher = ''
  for i in indexes:
    if i > len(alphabet)-1:
      i %= len(alphabet)
    ceaser_cipher = ceaser_cipher   (alphabet[i])
  print(ceaser_cipher)  

if en_de == "encrypt":
  encrypt()
elif en_de == "decrypt":
  decrypt()

CodePudding user response:

The structure I would go for, is like this:

input_string = input("Enter message or cipher: ")
input_list = input_string.split(" ")
# input_list will be a list of each word in input_string
# encrypt each word in input_list and append each encrypted word 
# to a new list, let's say that list is called output_list
output = " ".join(output_list)
# output will be a string of each item in the list separated by spaces

The final program could look something like this:

alphabet = list("abcdefghijklmnopqrstuvwxyz")
message = input("message or cipher: ").lower().split(" ")
shift = int(input("shift: "))
shifted_alphabet = alphabet[shift:]   alphabet[:shift]
cipher_list = []
for word in message:
    cipher_word = ""
    for letter in word:
        cipher_word  = shifted_alphabet[alphabet.index(letter)]
    cipher_list.append(cipher_word)
print(" ".join(cipher_list))

CodePudding user response:

You are in the right path in your learning, and @Toby's answer is a good contribution for you.

I'd like to just tease you here and let you know that the whole "Caesar Cipher" can be fully implemented in a one-liner, once you get familiar with many other Python features and syntax.

Check this:

''.join(chr(a   (i - a   shift) % 26) if (a := 65) <= (i := ord(c)) <= 90 or (a := 97) <= i <= 122 else c for c in word)

Examples:

cipher = lambda w, s: ''.join(chr(a   (i - a   s) % 26) if (a := 65) <= (i := ord(c)) <= 90 or (a := 97) <= i <= 122 else c for c in w)

word = 'Hello, beautiful World!'
print(cipher(word, 4)) # positive shift
# Lipps, fieyxmjyp Asvph!

word = 'Lipps, fieyxmjyp Asvph!'
print(cipher(word, -4)) # -4 shift means decipher a  4 shift
# Hello, beautiful World!

Explanation:

  • ''.join(seq) takes a sequence of strings seq and concatenate them together into one string;
  • ord(c) gives index of the character c in the Unicode table. For example, ord('a') returns the integer 97 and ord('A') returns the integer 65;
  • chr(i) is the inverse of ord: It gives the character at index i in the Unicode table. For example, chr(122) returns the string 'z' and chr(90) returns the string 'Z';
  • ... for c in word is a generator expression. Is a nice compact and efficient idiom for creating a sequence from another sequence. In this case, I am taking every character c in the string word, performing an operation, and creating a new sequence with each resulting element.
  • ... if ... else ... is the ternary operator. It is a shortcut to embed a condition in an expression. Here, if the character index is not between 65 and 90 (uppercase letters) or between 97 and 122 (lowercase letters), I am returning the same character c untouched. That makes any non-letter not get transformed by the cipher (like space, comma, or exclamation mark);
  • x <= y <= z is a chained comparisson, it is a nice idiom available in python that resembles the Math conditional expression.
  • (a := 65) and (i := ord(c)) make use of the walrus operator :=, aka "assignment expression". With this, you can assign a variable at the same time you use it in an expression, and this variable will be available for use in the enclosed context after the declaration. For example, i is assigned in the left side of the or operator, and is used in the right side. Also, a is assigned in the "test" part of the conditional and used in the "expression" part.
  • chr(a (i - a shift) % 26) is performing a modulo operation with the python's operator %, where 26 is the count of letters from A to Z. That means, if your shift makes your letter overflow the alphabet, it circles back to the beginning/end. For example, 'B' with a shift of -4 gives 'X', and 'x' with a shift of 30 gives 'b' (because 30 = 26 4);

It is a rather contrived implementation, but hopefully you got to know some new stuff today on python!

  • Related