I'd highly suggest learning comprehensions. The simplest is a list comprehension. This allows you to change say:
list = []
for x in string:
list.append(dic[x])
To:
list = [dic[x] for x in string]
However, you can get better memory usage by using a generator comprehension, this works in roughly the same way as a list, however you can't index it. Which for this code is fine. To do this replace the square brackets with curved ones:
gen = (dic[x] for x in string)
You can also use a dictionary comprehension to simplify your creation of dic2
:
dic2 = {v: k for k, v in dic.items()}
Purge all memory of eval
, it leads to poor code and has severe security vulnerabilities. Instead cast the users input to an int
. This can simplify decoding too. However you have to make sure the user does actually enter a number.
I don't like list = []
being outside the if
statement. There's not much of a need for this. However it's fixed when using comprehensions.
I also think you should use while True
rather than while program:
. As you never change program
.
Merging this all together gets you:
dic = {"A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7, "I": 8, "J": 9, "K": 10, "L": 11, "M": 12, "N": 13, "O": 14, "P": 15, "Q": 16, "R": 17, "S": 18, "T": 19, "U": 20, "V": 21, "W": 22, "X": 23, "Y": 24, "Z": 25, " ": 26}
dic2 = {v: k for k, v in dic.items()}
while True:
task = input("Would you like to encode or decode?: ").lower()
if task == "encode":
string = input("What would you like to encode?: ").upper()
while True:
try:
key = int(input("What key would you like to use?: "))
break
except ValueError:
pass
list = (dic[x] for x in string)
encodeNums = ((x + key) % 27 for x in list)
encodeStr = (dic2[x] for x in encodeNums)
print("".join(encodeStr))
Going forward, I'd change your code to encode and decode with the same code. This is as the Caesar cipher is a symmetric cypher, so simply using key = -key
allows you to decode the encoding.
Allowing:
dic = {"A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7, "I": 8, "J": 9, "K": 10, "L": 11, "M": 12, "N": 13, "O": 14, "P": 15, "Q": 16, "R": 17, "S": 18, "T": 19, "U": 20, "V": 21, "W": 22, "X": 23, "Y": 24, "Z": 25, " ": 26}
dic2 = {v: k for k, v in dic.items()}
while True:
string = input("What would you like cypher?: ").upper()
task = input("Would you like to encode or decode?: ").lower()
while True:
try:
key = int(input("What key would you like to use?: "))
break
except ValueError:
pass
if task == "decode":
key = -key
list = (dic[x] for x in string)
encodeNums = ((x + key) % 27 for x in list)
encodeStr = (dic2[x] for x in encodeNums)
print("".join(encodeStr))