Python Caesar cipher decoding - python

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()

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.

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:
Exclude non-alphabetic characters from the Caesar cypher.
Make sure that letters wrap when approach the end: A - 1 should equal Z.

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.)

Related

How do you split duplicate letters with "x" in Python?

I am trying to create a function which is able to detect when two letters back to back are duplicates, for example the ls in "hello", and split the duplicate letters with the letter "x". Here is my code:
plaintext = input("Enter plaintext here: ")
plaintext = plaintext.lower() # makes plaintext lowercase
plaintext = plaintext.replace(" ", "") # removes all spaces
# this separates all duplicate letters
i = 0 # sets i to 0
for letter in plaintext:
if plaintext[-1] == plaintext[-2]: # if the last letter is the same as the second to last
plaintext = plaintext[:-1] + "x" + plaintext[-1:] # separate them with an x
elif plaintext[i] == plaintext [i+1]: # if one letter is the same as the next letter
# the line above makes an error
plaintext = plaintext[:i+1] + "x" + plaintext[i+1:] #separate them with an x
i += 1
else:
i += 1
This code works when I enter hello there as the input; I receive helxlothere. However, when I test another input, such as heythere, IndexError: string index out of range shows up for elif line (line 12). How can I make this code work for all inputs?
You can use regex to achieve this.
For both approaches, it will work for hello there hey there
The difference comes when more than two character repetition happens.
approach 1
import re
string='hello there'
# find Any repeated character and add x in between them
answer = re.sub(r'(.)\1{1}', r'\1x\1', string)
print(answer)
Here for hellllo there text, you will get output helxllxlo there
approach 2
alternatively, you can use this method.
s="hello there"
for match in re.finditer(r"(.)\1+", s):
old=s[match.start():match.end()]
s=s.replace(old,'x'.join(old))
print(s)
here for hellllo there text, you will get output helxlxlxlo there as output.
I think the second approach will be more appropriate.
The IndexError is caused by the fact that you are looking at plaintext[i+1]. As you can see in the word heythere, there are no letters which match back to back, and therefore the code continues until it hits the end, and so you get an IndexError because there is no element i+1.
You can fix this by using this code instead:
plaintext = input("Enter plaintext here: ")
plaintext = plaintext.lower() # makes plaintext lowercase
plaintext = plaintext.replace(" ", "") # removes all spaces
# this separates all duplicate letters
i = 0 # sets i to 0
for letter in plaintext:
if plaintext[-1] == plaintext[-2]: # if the last letter is the same as the second to last
plaintext = plaintext[:-1] + "x" + plaintext[-1:] # separate them with an x
try:
elif plaintext[i] == plaintext [i+1]: # if one letter is the same as the next letter
# the line above makes an error
plaintext = plaintext[:i+1] + "x" + plaintext[i+1:] #separate them with an x
i += 1
else:
i += 1
except IndexError:
pass
This code should stop your code from crashing in the elif statement, while also completing properly.
Hope this helps, have a nice day!
You are receiving the IndexError because during iterating, when the loop reaches the last letter,
elif plaintext[i] == plaintext [i+1]:
this line checks for the letter after the last letter, which does not exist, which causes the program to run into IndexError.
You have to check till the second last letter, for it to work properly.
A simple and easier way to arrive at the same output with a bit easier logic.
Logic
Create a new string and insert all letters which are in the old string, plaintext, to the new string, newPlainText, and check only for one condition that is whether the last letter is same as current or not and if yes then also insert letter 'x' into the newPlainText and that's it!
plaintext = input("Enter plaintext here: ")
plaintext = plaintext.lower() # makes plaintext lowercase
plaintext = plaintext.replace(" ", "") # removes all spaces
# this separates all duplicate letters
newPlainText = plaintext[0] # copy the first letter of plaintext to the new string which will handle the duplicates and insert `x` between them
i = 1 # sets i to 1
while i < len(plaintext):
if plaintext[i] == plaintext[i-1]: # we check that if prev and current letters are same then also append x to the new string
newPlainText += "x"
newPlainText += plaintext[i] # we insert the required current letter to the new string in each iteration
i += 1
print(newPlainText)

Selecting specific int values from list and changing them

I have been playing with Python and came across a task from MIT, which is to create coded message (Julius Cesar code where for example you change ABCD letters in message to CDEF). This is what I came up with:
Phrase = input('Type message to encrypt: ')
shiftValue = int(input('Enter shift value: '))
listPhrase = list(Phrase)
listLenght = len(listPhrase)
ascii = []
for ch in listPhrase:
ascii.append(ord(ch))
print (ascii)
asciiCoded = []
for i in ascii:
asciiCoded.append(i+shiftValue)
print (asciiCoded)
phraseCoded = []
for i in asciiCoded:
phraseCoded.append(chr(i))
print (phraseCoded)
stringCoded = ''.join(phraseCoded)
print (stringCoded)
The code works but I have to implement not shifting the ascii value of spaces and special signs in message.
So my idea is to select values in list in range of range(65,90) and range(97,122) and change them while I do not change any others. But how do I do that?
If you want to use that gigantic code :) to do something as simple as that, then you keep a check like so:
asciiCoded = []
for i in ascii:
if 65 <= i <= 90 or 97 <= i <= 122: # only letters get changed
asciiCoded.append(i+shiftValue)
else:
asciiCoded.append(i)
But you know what, python can do the whole of that in a single line, using list comprehension. Watch this:
Phrase = input('Type message to encrypt: ')
shiftValue = int(input('Enter shift value: '))
# encoding to cypher, in single line
stringCoded = ''.join(chr(ord(c)+shiftValue) if c.isalpha() else c for c in Phrase)
print(stringCoded)
A little explanation: the list comprehension boils down to this for loop, which is easier to comprehend. Caught something? :)
temp_list = []
for c in Phrase:
if c.isalpha():
# shift if the c is alphabet
temp_list.append(chr(ord(c)+shiftValue))
else:
# no shift if c is no alphabet
temp_list.append(c)
# join the list to form a string
stringCoded = ''.join(temp_list)
Much easier it is to use the maketrans method from the string module:
>>import string
>>
>>caesar = string.maketrans('ABCD', 'CDEF')
>>
>>s = 'CAD BA'
>>
>>print s
>>print s.translate(caesar)
CAD BA
ECF DC
EDIT: This was for Python 2.7
With 3.5 just do
caesar = str.maketrans('ABCD', 'CDEF')
And an easy function to return a mapping.
>>> def encrypt(shift):
... alphabet = string.ascii_uppercase
... move = (len(alphabet) + shift) % len(alphabet)
... map_to = alphabet[move:] + alphabet[:move]
... return str.maketrans(alphabet, map_to)
>>> "ABC".translate(encrypt(4))
'EFG'
This function uses modulo addition to construct the encrypted caesar string.
asciiCoded = []
final_ascii = ""
for i in ascii:
final_ascii = i+shiftValue #add shiftValue to ascii value of character
if final_ascii in range(65,91) or final_ascii in range(97,123): #Condition to skip the special characters
asciiCoded.append(final_ascii)
else:
asciiCoded.append(i)
print (asciiCoded)

Python 2 Caesar Cipher

My question is how to improve the code so that it can adapt to however long the input message is. As is, the message must be 5 letters. I would like to improve the code such that a message of any length can be inputted and the cipher will work with it. Help would be much appreciated. :-) See the code below!
#Enter your message
message=raw_input('Enter your message here. Make sure to use all CAPS througout your message and leave no spaces in between words.')
length=len(message)
print 'The length of your message is ',length
#This statement is a possible idea to let the program know how many letters it will be need to shift. But I don't know how to actually do this.
print chr(length+64)
#Indexes letters out of message.
A=message[length-length]
B=message[length-length+1]
C=message[length-length+2]
D=message[length-length+3]
E=message[length-length+4]
#Shifts letters and accounts for shifting XYZ to ABC.
def shift(x):
if ord(x)+3==91:
return 65
if ord(x)+3==92:
return 66
if ord(x)+3==93:
return 67
else:
return ord(x)+3
a2=shift(A)
b2=shift(B)
c2=shift(C)
d2=shift(D)
e2=shift(E)
#Converts shifted ordinals back to characters
def convert(x):
return chr(x)
first=convert(a2)
second=convert(b2)
third=convert(c2)
fourth=convert(d2)
fifth=convert(e2)
#Prints resultant characters
print first,second,third,fourth,fifth
import string
shift_amt = 13
alphabet_lc = string.ascii_lowercase
shifted_lc = alphabet_lc[shift_amt:]+alphabet_lc[:shift_amt]
alphabet_uc = alphabet_lc.upper()
shifted_uc = shifted_lc.upper()
trans_tab = string.maketrans(alphabet_lc+alphabet_uc,shifted_lc+shifted_uc)
message = "Encode Me To a new MessaGez!"
print message.translate(trans_tab)
is one way of doing it in Python2 at least
Use two for loops, one for looping through each character, and one for shifting the character the desired amount of times. We use a function upper() to shift a character.
def upper(char):
from string import ascii_letters as _all
if char == ' ':
return ' '
return _all[_all.index(char)+1] if char != 'Z' else 'a'
def shift(message, key):
temp = []
for i in message:
char = i
for k in range(key):
char = upper(char)
temp.append(char)
return ''.join(temp)
message=raw_input('Enter your message here: ')
key = int(raw_input('Enter the desired key: '))
length=len(message)
print 'The length of your message is', length
print 'Your encrypted message is {0}'.format(shift(message, key))
This runs as:
bash-3.2$ python caesar.py
Enter your message here: This works WITH or without CAPS
Enter the desired key: 10
The length of your message is 31
Your encrypted message is drsC GyBuC gSdR yB GsDryED MKZc
bash-3.2$
The Ceasar cipher is built in in python 2;
In [6]: 'The Caesar cipher is built-in.'.encode('rot13')
Out[6]: 'Gur Pnrfne pvcure vf ohvyg-va.'
As you can see, this encoding only acts on letters, and it works for upper and lower case.
But is you want to remove spaces and make every thing upper-case, Python can do that as well;
In [9]: 'this is a string'.translate(None, ' \t')
Out[9]: 'thisisastring'
In [10]: 'this is a string'.translate(None, ' \t').upper()
Out[10]: 'THISISASTRING'
In [11]: 'this is a string'.translate(None, ' \t').upper().encode('rot13')
Out[11]: 'GUVFVFNFGEVAT'
Or in a different way;
In [15]: ''.join('this is a string'.split()).upper().encode('rot13')
Out[15]: 'GUVFVFNFGEVAT'
Bibliography:
Kid Snippets: "Math Class" (Imagined by Kids) - YouTube http://youtu.be/KdxEAt91D7k
Mary Had A Little Lamb Nursery Rhyme With Lyrics - YouTube http://youtu.be/CkRdvGmcCBE
Mary Had a Little Lamb - Wikipedia, the free encyclopedia http://goo.gl/FNEuyd
Python source code:
Note: working for negative shift numbers also
Note: if reverse shift then we do encode - decode message
Note: preserving spaces also
small_chars = [chr(item) for item in range(ord('a'), ord('z')+1)]
upper_chars = [item.upper() for item in small_chars]
def encode_chr(chr_item, is_upper_case):
'''
Cipher each chr_item.
'''
# setting orig and end order.
if is_upper_case:
orig_ord = ord('A')
end_ord = ord('Z')
else:
orig_ord = ord('a')
end_ord = ord('z')
# calculating shift
temp_ord = ord(chr_item)+shift
# calculating offset order with modulo.
# char is after end_ord, calculating offset
num_of_chars = 26
offset_ord = (temp_ord - end_ord - 1)%num_of_chars
return chr(orig_ord + offset_ord)
# enable while loop to repeat until status not 'y'
status = 'y'
while status == 'y':
# enter word to cipher.
word = raw_input("Word: ")
# enter char shift
shift = input("Shift: ")
print
# create cipher list variable
cipher = list()
# loop trough each char in word
for chr_item in word:
# encode just letters.
# replace non-alfa with underscore: "_"
if chr_item in upper_chars or chr_item in small_chars:
# set is_uppser_case to True for upper case chars.
is_upper_case = (chr_item in upper_chars) and True
# cipher char.
temp_chr = encode_chr(chr_item, is_upper_case)
# append ciphered char to list
cipher.append(temp_chr)
elif chr_item is ' ':
cipher.append(chr_item)
else:
cipher.append('_')
# print word
print word
# print ciphered word
print ''.join(cipher)
# repeat again for another word?
status = raw_input("Repeat? [y|n]: ")
print
Test cases:
>>>
Word: aAzZ!#
Shift: 1
aAzZ!#
bBaA__
Repeat? [y|n]: y
Word: aAzZ#!
Shift: -1
aAzZ#!
zZyY__
Repeat? [y|n]: y
Word: aAzZ#$
Shift: 27
aAzZ#$
bBaA__
Repeat? [y|n]: y
Word: aAzZ%^
Shift: -27
aAzZ%^
zZyY__
Repeat? [y|n]: n
>>>
Output:
Note: if reverse shift then we do encode - decode message
>>>
Word: "Mary Had a Little Lamb"
Shift: 1
"Mary Had a Little Lamb"
_Nbsz Ibe b Mjuumf Mbnc_
Repeat? [y|n]: y
Word: _Nbsz Ibe b Mjuumf Mbnc_
Shift: -1
_Nbsz Ibe b Mjuumf Mbnc_
_Mary Had a Little Lamb_
Repeat? [y|n]: n
>>>
Here is a simple Caesar cipher program written for Python 3 that should not be very difficult to rewrite for Python 2:
import string
def main():
key = 5
table = str.maketrans(string.ascii_letters,
string.ascii_lowercase[key:] +
string.ascii_lowercase[:key] +
string.ascii_uppercase[key:] +
string.ascii_uppercase[:key])
plaintext = input('Please enter a phrase: ')
ciphertext = plaintext.translate(table)
print('Your encrypted phrase is:', ciphertext)
if __name__ == '__main__':
main()

Need To Write Program to Decode Alphabet for Secret Message [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
So, I need to input a scrambled alphabet, and then input a secret message using that alphabet. My program needs to unscramble the secret message. I have written this so far and am stuck. I was hoping someone could help me. What I tried so far is changing every index in the list to A-Z. My question is how do I use what I wrote for that and make it work for the secret message I input as well.
s = ()
alphabet = input("Please input the scrambled alphabet in order: ")
message = input("Now input the scrambled message: ")
alphabet.upper()
s = dict(alphabet)
num = 1
while num < 2:
s[0] = chr(65)
s[1] = chr(66)
s[2] = chr(67)
s[3] = chr(68)
s[4] = chr(69)
s[5] = chr(70)
s[6] = chr(71)
s[7] = chr(72)
s[8] = chr(73)
s[9] = chr(74)
s[10] = chr(75)
s[11] = chr(76)
s[12] = chr(77)
s[13] = chr(78)
s[14] = chr(79)
s[15] = chr(80)
s[16] = chr(81)
s[17] = chr(82)
s[18] = chr(83)
s[19] = chr(84)
s[20] = chr(85)
s[21] = chr(86)
s[22] = chr(87)
s[23] = chr(88)
s[24] = chr(89)
s[25] = chr(90)
num +=1
print (s)
for alpha in message.upper():
if alpha < "A" or alpha > "Z":
print(alpha,end="")
else:
print(s [ord(alpha) -65 ], end="")
First, creating the big dictionary s is entirely unnecessary. It literally does nothing: the line:
s [ord(alpha) -65 ]
Is turning a letter into a number, subtracting 65, and then putting it through a dictionary that adds 65 and turns it back into a number.
Secondly, the line alphabet.upper() doesn't actually change the alphabet, it just returns an uppercase version. You need to do
alphabet = alphabet.upper()
Now for the meaty part. What you meant to do was create a dictionary mapping letters in the code alphabet to letters in the real alphabet. The line dict(alphabet) doesn't do this. Instead, iterate through the characters in the string and assign each to the corresponding letter. You're on the right track using chr, but are going to way too much work. How about this:
s = {}
for i in range(26): # iterate from 0 to 25
s[alphabet[i]] = chr(65 + i)
since chr(65 + i) is the letter in the normal, ordered alphabet, and alphabet[i] is the scrambled one.
Once you have that dictionary, running through letter by letter and changing it should be easy (and it's left to you).
You could use the string translate() method:
import string
intab = 'abcdefghijklmnopqrstuvwxyz' # or string.ascii_lowercase
outtab = 'xyzabcdefghijklmnopqrstuvw'
tab = string.maketrans(intab, outtab)
s = raw_input('Type some text: ').lower()
print s.translate(tab)
maketrans() creates a table with both alphabets, and translate() just replace each character of the string by its pair in the table.
I don't know Python - this is pseudocode
create array of scrambled alphabet
create array of "normal" alphabet
foreach char in message, find char in scrambled array, then output corresponding "normal" char
You could make a dictionary:
alphabet({'a':'alpha', 'b':'bravo','c':'charlie', etc.})
so abc would translate to alphabravocharlie
where 'a','b',.. are the coded letters and 'alpha','bravo',... are their actual values. Make "cypher" by reversing this.
See the section of online tutorials on dictionaries:
http://docs.python.org/dev/library/collections.html
I believe you're asking 'If I type in a string of characters (I'm assuming a string with no delimiter), how can I make that a dictionary where the first letter = A, the second = B, etc.' (sorry if this is the incorrect interpretation). If that is the case, you could do something like this (note the usage of raw_input - input is a built-in that evaluates the parameter - it will not assign):
alphabet = raw_input("Please input the scrambled alphabet in order: ")
message = raw_input("Now input the scrambled message: ")
secret_map = {}
# Step through the provided string, incrementing the character number by index.
# Index will start at 65 + 0 = A (change to 98 if you want lowercase)
for index, letter in enumerate(alphabet):
secret_map[letter] = chr(65 + index)
# Now join the string together, mapping each letter to its corresponding value
new_str = ''.join([secret_map[char] for char in message])
# Print the resulting string
print new_str
Since this is homework (and perhaps you haven't gotten to list comprehensions), this is equivalent to creating new_str:
new_str = ''
for letter in message:
new_str += secret_map[letter]
Let me know if this isn't what you were looking for.
I just couldn't resist expanding on stummjr's answer to create a more pythonic version of both encoding and decoding (I added some extra variables to try and make each step more clear):
import random, string
cypher_list = list(string.ascii_lowercase)
random.shuffle(cypher_list)
cypher_text = ''.join(cypher_list)
encode_tab = string.maketrans(string.ascii_lowercase, cypher_text)
decode_tab = string.maketrans(cypher_text, string.ascii_lowercase)
orig_text = 'this means war'
crypt_text = orig_text.translate(encode_tab)
clear_text = crypt_text.translate(decode_tab)
print cypher_text
print crypt_text
print clear_text
assert(clear_text == orig_text)

Modifying a program to Decrypt a message using a past encrypted alphabet on python

I need help in writing the second part to this program, which is almost complete. I finish writing the part in which an alphabet is encrypted, but now I find myself stuck in trying to use the new encryption as a sort of decoder ring, to decrypt a a random scrambled message that someone might input into the program.
So to makes this easier to understand, lets say the encryption part of this program gives you: NHPWJXEYOZMAFUSCIGLVTDBKRQ
Now someone would type some random message encrypted using the new scrambled alphabet. So lets say someone types: VYOL OL FR 1LV LJPGJV FJLLNEJ!
Now the program that I need to write will have to use the scrambled alphabet to decoded the message and print: THIS IS MY 1ST SECRET MESSAGE!
If anyone can help, I'll appreciate it. If it still sounds confusing, just ask. Th program that I have is below:
# ENCODE a secret message
# Scramble the alphabet, read a secret message, encode it, print scrambled
import random
def main():
encryption()
decryption()
def encryption():
encrypt=["*"]*26 # all letters available
print(encrypt)
print("Alphabet: ", end="")
for numbah in range(26):
#converts numbah into a letter
letter = chr(numbah+65) # converts 0-25 --> 'A' = 'Z'
print(letter, end="")
#Reminder: find an empty position for that letter to be placed
notfound = True
while notfound:
possible_position = random.randint(0,25)
if encrypt[possible_position] == "*":
notfound = False
encrypt[possible_position] = letter
print("\nScrambled: " , end="")
for numbah in range(26):
print(encrypt[numbah], end="")
print("\n\n")
msg=input("Now, please type your secret message to encode: ")
print("Your secret message: " + msg)
print("Your message encoded: ", end="")
# reminder non alphabetic characters should 'float thru' unchanged!
for alpha in msg.upper():
if alpha < "A" or alpha > "Z":
print(alpha, end="")
else:
print( encrypt[ ord(alpha) - 65], end="")
print("\n")
def decryption():
scram_alph = input("Input the scrambled alphabet from the early prog: ")
scram_mess = input("Input the scrambled messgae you want decoded: ")
main()
There are functions in the Python standard library that make this task quite easy. Have a look at str.translate() and string.maketrans():
>>> import string
>>> t = string.maketrans("NHPWJXEYOZMAFUSCIGLVTDBKRQ",
string.ascii_uppercase)
>>> "DRSA SA XG 1AD AZCEZD XZAAUJZ!".translate(t)
'THIS IS MY 1ST SECRET MESSAGE!'
You're waaaaaay overcomplicating it. Use the built-in iteration tools that Python gives you.
>>> alphabet = "NHPWJXEYOZMAFUSCIGLVTDBKRQ".lower()
>>> message = "VYOL OL FR 1LV LJPGJV FJLLNEJ!".lower()
>>>
>>> table = dict(zip(alphabet, string.ascii_lowercase))
>>> "".join(table.get(char, char) for char in message)
'this is my 1st secret message!'
Explanation
The line
table = dict(zip(alphabet, string.ascii_lowercase))
makes a dictionary of ciphertext letters to plaintext letters. Why? zip of two strings gives you a list of pairs: (first letter, first letter), (second letter, second letter), etc. Then dict of that makes a dictionary. Then the line
"".join(table.get(char, char) for char in message)
says to look up each character in the message in the dictionary (and if it's not there e.g. it's a space or a ! then don't change it) and glue them back into a string.
By the way, to make a scrambled alphabet all you need to do is
>>> alphabet = list(string.ascii_lowercase)
>>> random.shuffle(alphabet)
>>> alphabet = "".join(alphabet)
>>> alphabet
'emxcqgzvkruisjtlydbhafopnw'

Categories

Resources