I'm currently working on this code now..
message = input("Enter ASCII codes: ")
decodedMessage = ""
for item in message.split():
decodedMessage += chr(int(item))
print ("Decoded message:", decodedMessage)
#1st Run:
Enter ASCII codes: 97
Decoded message: a
#2nd Run:
Enter ASCII codes: 9797
Decoded message: ♅
The result I want is: aa which is from 97 and another 97 of ascii codes.
How can this be done?
I want it like this.
ord_username = input("Enter Username:")
letters = str(ord_username)
ordlist=[]
z=""
for letter in letters:
number = ord(letter)
ordlist.append(number)
for i in ordlist:
z += str(i) + ""
print (z)
#1st Run:
Enter Username:a
97
#2nd Run:
Enter Username:ab
9798
You want to interpret your string as being composed of 3-digit strings beginning with a '1' or 2-digit strings that cannot begin with a 1. Because of that, you can move through the string from start to finish, plucking out three characters if the first is a 1 or two characters if it isn't. This just needs a simple method:
def stringsplit(message):
message_split = []
while len(message) > 0:
if message[0] == '1':
message_split.append(message[:3])
message = message[3:]
else:
message_split.append(message[:2])
message = message[2:]
return message_split
Then, replace for item in message.split(): with for item in stringsplit(message):
Caveat: Python 2.7 implementation; your mileage may vary, but it shouldn't.
Related
So when I encode "hello" in my Encode() function, with a shift of three I get the result "khoor". When I attempt to decode "khoor" using my decode function with a shift of three, I get "hellor". This is strange because an extra letter "r" is returned, despite only decoding 5 letters. This happens with every string I attempt to decode, and I have noticed that the last letter of every string to be encoded is added as an additional letter to the decoded string.
ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
def Menu():
print("Please choose from the following: \n")
print("'e' to encode a string.")
print("'d' to decode a string.")
print("'q' to quit.\n")
choice = input("Please enter one of the letters above.\n")
if choice == "e":
print (Encode())
if choice == "d":
print (Decode())
if choice == "q":
print("The program will now exit.")
quit()
def stringValidation():
while True:
try:
valid = str(input("Enter a string to encode.\n"))
return valid
break
except:
print("Value Error. Enter a string with only letters from the alphabet.")
continue
def shiftValidation():
while True:
try:
valid = int(input("Enter the number of shifts you would like.\n"))
return valid
break
except:
print("Value Error. Please enter an integer.")
def decodeShiftValidation():
while True:
try:
valid = int(input("Enter the key. (Number of shifts used to encrypt the encoded word.)\n"))
return valid
break
except:
print("Value Error. Please enter an integer.")
def Encode():
data = []
string = stringValidation() # asks the user for the string input to be encoded
shift = shiftValidation() # asks the user for the number of shifts
for i in string: # for the letters in string...
if i.strip() and i in ALPHABET: # i.strip removes all default whitespace characters from i (string input by user.)
data.append(ALPHABET[(ALPHABET.index(i) + shift) % 26]) # gets position of the letters from input string in ALPHABET using indexing, and adds the shift to get the new position and new letter.
else:
data.append(i) # if it is a space, simply append it to the data.
output = ''.join(data)
return output
encoded_string= Encode()
print(encoded_string)
def Decode():
data = []
string = input("Please enter the string you wish to decode.\n")
shift = int(input("Enter the key. (Number of shifts used when encoding original word. \n"))
for i in string:
if i.strip() and i in ALPHABET:
data.append(ALPHABET[(ALPHABET.index(i) - shift) % 26])
else:
data.append(i)
output = ''.join(data)
return output
Menu()
An indentation error makes the else of your Decode function a else for the for loop (which is a lesser-known feature of for loop: if no break is encountered, the else executes, adding an extra letter in your case).
That explains why you don't get an error but unexpected behaviour.
More here: Why does python use 'else' after for and while loops?
Aside, a very clumsy way to search in the alphabet is to use index, when you can compute the index directly with characters codes:
data.append(ALPHABET[(ord(i)-ord(ALPHABET[0]) + shift) % 26])
Aside #2: note that decode & encode methods are very similar. Factorize them with the shift as parameter (which is the opposite from one method to the other)
I got errors trying to run your script until I changed all of the input statements to raw_input. But I don't quite understand the logic behind if i.strip() and i in ALPHABET:. Also, you don't have to accumulate letters in a list one at a time and then join them back, when Python lets you append strings directly. In any case, when I simplified your Decode() function to the following, it worked for me:
def Decode():
string = raw_input("Please enter the string you wish to decode.\n").lower().strip()
if string.isalpha():
shift = int(raw_input("Enter the key. (Number of shifts used when encoding original word. \n"))
return ''.join([ ALPHABET[(ALPHABET.index(c) - shift) % 26] for c in string])
I also added in a .lower() and .isalpha() check in case the user uses any capital letters or non-alphabetic strings, but there are other things like this you can add to handle other use cases.
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)
This question already has answers here:
Repeat string to certain length
(15 answers)
Closed 5 months ago.
In school we are currently using python to create a Caeser Cipher, and a Keyword Cipher. I need help with certain parts of the Keyword cipher, mainly repeating a word to match the length of a string that has been entered, For example:
Entered String: Hello I am Jacob Key: bye Printed text: byebyebyebyeb
I'm okay at Python, but this is very hard for me. Currently this is as far as I got:
def repeat_to_length(key, Input):
return (key * ((ord(Input)/len(key))+1))[:ord(Input)]
Since It's a string I thought if I used ord It would turn it to a number, but I realised when using the ord command you can only have a single character, as I realised when I repeatedly got this error:
TypeError: ord() expected a character, but string of length 16 found
I found some code that did a keyword cipher, but I am not sure which part does the process I am trying to code:
def createVigenereSquare():
start = ord('a')
end = start + 26
index = start
sq = [''] * 256
for i in range(start, end):
row = [''] * 256
for j in range(start, end):
if index > (end - 1):
index = start
row[j] = chr(index)
index += 1
sq[i] = row
index = i + 1
return sq
def createKey(message, keyword):
n = 0
key = ""
for i in range(0, len(message)):
if n >= len(keyword):
n = 0
key += keyword[n]
n += 1
return key
def createCipherText(message, key):
vsquare = createVigenereSquare()
cipher = ""
for i in range(0, len(key)):
cipher += vsquare[ord(key[i])][ord(message[i])]
return cipher
message = str(input("Please input a message using lowercase letters: "))
keyword = str(input("Please input a single word with lowercase letters: "))
key = createKey(message, keyword)
ciphertext = createCipherText(message, key)
print ("Message: " + message)
print ("Keyword: " + keyword)
print ("Key: " + key)
print ("Ciphertext: " + ciphertext)
As I've said I'm only okay at Python, so I don't really understand all the code in the above code, and I really want to be able to write most of it myself.
This is my code so far:
def getMode():
while True:
print("Enter encrypt, e, decrypt or d")
mode = input('Do you want to encrypt the message or decrypt? ') #changes whether the code encrypts or decrypts message
if mode in 'encrypt e decrypt d ENCRYPT E DECRYPT D'.split(): #defines the various inputs that are valid
return mode
else:
print('Enter either "encrypt" or "e" or "decrypt" or "d".') #restarts this string of code if the input the user enters is invalid
Input = input('Enter your message: ')
key = input('Enter the one word key: ')
def repeat_to_length(key, Input):
return (key * ((ord(Input)/len(key))+1))[:ord(Input)]
encryptedKey = repeat_to_length(key, Input)
print(encryptedKey)
I know I've been pretty long winded but if anyone could provide any information on this topic, like explaining the code for the keyword cipher, or just answering my question, I would appreciate it!
AnimeDeamon
Another possibility is to repeat the key enough times to get a string at least as long as the message, and then just grab as many characters as you need from the beginning:
>>> message='Hello I am Jacob'
>>> key='bye'
>>> times=len(message)//len(key)+1
>>> print((times*key)[:len(message)])
byebyebyebyebyeb
We compute times by dividing the length of the message by the length of the string, but we have to add 1, because any remainder will be dropped. times*key is just key repeated times times. This may be longer than we want, so we just take the first len(message) characters.
A simple one-liner could be
''.join(key[i % len(key)] for i in range(len(message)))
What it does, inside out:
We iterate over the indices of the letters in the string message
For each index, we take the remainder after division with the key length (using the % operator) and get the corresponding letter from the key
A list of these letters is constructed (using list comprehension) and joined together to form a string (the join method of an empty string)
Example:
>>> message = "Hello I am Jacob"
>>> key = "bye"
>>> print ''.join(key[i % len(key)] for i in range(len(message)))
byebyebyebyebyeb
The output I should get if I type in "eat" should be "hdw" if I shift it by 3. However, the end result is only "w". I'm pretty sure I have everything I need, but maybe it's the formatting?
def shifter():
phrase = input("Please enter a message: ")
key = eval(input("Please enter the number of places to be shifted: "))
list = phrase.split()
for word in list:
for ch in word:
conversion = (chr)((ord(ch) - ord("a") + key) % 26 + ord("a"))
newPhrase = " "
newPhrase = newPhrase + conversion
print(newPhrase)
shifter()
The issue is that you are setting conversion inside your for loop, instead of appending to it, so only the last character in the word is appended to the newPhrase at the end.
You should be appending to conversion, rather than setting it.
Also, you should initialize newPhrase outside the loop and then append to it inside.
Example -
def shifter():
phrase = input("Please enter a message: ")
key = eval(input("Please enter the number of places to be shifted: "))
list = phrase.split()
newPhrase = ""
for word in list:
conversion = ''
for ch in word:
conversion += (chr)((ord(ch) - ord("a") + key) % 26 + ord("a"))
newPhrase = newPhrase + conversion + " "
print(newPhrase)
shifter()
I think it's with your indenting!
Right now, before you do anything with the variable conversion, you've already looped through every ch in word, so you're stuck at the last ch.
Try doing conversion += ... Instead of conversion = ...
(You might need to initialize conversion before that but idts.)
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()