Here is some code of mine for a function used to decrypt a ceaser cipher. The approach used when the shift is not known is simply to get every possible value, then pick the one with more then half the decoded words being in the English dictionary. For non alphabetic characters, there is a placeholder character used.
There are some extra parts required, such as the dictionary or extra functions / lists so I will include them in the below links.
A note, it does only work for on lowercase letters however, I do hope it will help you to understand the logic a bit better.
def Decode(message, shift=-1):
"""
Decodes a message from a caesar cipher
Params:
- message (str) : Message to decode
Optional Params:
- shift (int) : If shift is known
Returns:
- decodedMessage (str) : The decoded message
"""
decodedMessage = ''
message = message.lower() # lowercase is easier to work with
# If the shift is known it is simple to decode
if shift != -1:
for letterIndex in range(len(message)):
if message[letterIndex] in [' ', '!', '?', '.', '-', ',', '_']:
decodedMessage += message[letterIndex]
else:
try:
index = ALPHABET.index(message[letterIndex]) - shift
# If the index is smaller then ALPHABET, handle it
while index < 0:
index += len(ALPHABET)
decodedMessage += ALPHABET[index]
except Exception as e:
print("A problem occured:", e)
decodedMessage += '?'
return decodedMessage
else: #If shift is not known, figure it out thru brute force
data = read_json('words_dictionary')
for i in range(len(ALPHABET)):
decodedMessage = Decode(message, i+1)
wordList = decodedMessage.split(" ")
try:
# Loop over words counting english words
count = 0
for word in wordList:
if word in data.keys():
count += 1
# More accurate this way compared to only one word checks
if count > len(wordList) / 2:
return decodedMessage
except KeyError:
continue
Full code here
Word dictionary here