Python Caesar Cipher Decoder

decoding, encryption, python

Solution

My final solution that works, thanks to the wonderful Cristian Ciupitu.

x = input()
NUM_LETTERS = 26 #Can't import modules I'm using a web based grader/compiler
def SpyCoder(S, N):
   y = ""
   for i in S:
      if(i.isupper()):
         x = ord(i)
         x += N
         if x > ord('Z'):
            x -= NUM_LETTERS
         elif x < ord('A'):
            x += NUM_LETTERS
         y += chr(x)
      else:
         y += " "
   return y

def GoodnessFinder(S):
   y = 0
   for i in S:
      if i.isupper():
         x = ord(i)
         x -= ord('A')
         y += letterGoodness[x]
      else:
         y += 1
   return y

def GoodnessComparer(S):
   goodnesstocompare = GoodnessFinder(S)
   goodness = 0
   v = ''
   best_v = S
   for i in range(0, 26):
     v = SpyCoder(S, i)
     goodness = GoodnessFinder(v)
     if goodness > goodnesstocompare:
         best_v = v
         goodnesstocompare = goodness
   return best_v


print(GoodnessComparer(x))

Thank you for all of your help!

Problem

In my lesson I was tasked with creating a Caesar Cipher decoder that takes a string of input and finds the best possible string using a letter frequencies. If not sure how much sense that made but let post the question: Write a program which does the following. First, it should read one line of input, which is the encoded message, and will consist of capital letters and spaces. Your program must try decoding the message with all 26 possible values of the shift S; out of these 26 possible original messages, print the one which has the highest goodness. For your convenience, we will pre-define the variable letterGoodness for you, a list of length 26 which equals the values in the frequency table above I have this code so far: ``` x = input() NUM_LETTERS = 26 #Can't import modules I'm using a web based grader/compiler def SpyCoder(S, N): y = "" for i in S: x = ord(i) x += N if x > ord('Z'): x -= NUM_LETTERS elif x < ord('A'): x += NUM_LETTERS y += chr(x) return y def GoodnessFinder(S): y = 0 for i in S: if x != 32: x = ord(i) x -= ord('A') y += letterGoodness[x] return y def GoodnessComparer(S): goodnesstocompare = GoodnessFinder(S) goodness = 0 v = '' for i in range(0, 26): v = SpyCoder(S, i) goodness = GoodnessFinder(v) if goodness > goodnesstocompare: goodnesstocompare = goodness return v y = x.split() z = '' for i in range(0, len(y)): if i == len(y) - 1: z += GoodnessComparer(y[i]) print(z) ``` EDIT: Made changes suggested by Cristian Ciupitu Please ignore indentation errors, they probably arose when I copied my code over. The program works like this: - Take the input and split it into a list - For every list value I feed it to a goodness finder. - It takes the goodness of the string and compares everything else against and when there's a higher goodness it makes the higher one the goodness to compare. - It then shifts that string of text by i amount to see if the goodness is higher or lower I'm not quite sure where the problem is, the first test: LQKP OG CV GKIJV DA VJG BQQ Prints the correct message: JOIN ME AT AT BY THE ZOO However the next test: UIJT JT B TBNQMF MJOF PG UFYU GPS EFDSZQUJOH Gives the a junk string of: SGHR HR Z RZLOKD KHMD NE SDWS ENQ CDBQXOSHMF When it's supposed to be: THIS IS A SAMPLE LINE OF TEXT FOR DECRYPTING I know I have to: Try every shift value Get the 'goodness' of the word Return the string with the highest goodness. I hope my explanation made sense as I am quite confused at the moment.

Original source