Python Caesar Cipher Decoder

后端 未结 3 541
抹茶落季
抹茶落季 2021-01-03 06:00

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 m

相关标签:
3条回答
  • 2021-01-03 06:14

    I'm working on the same tutorial and used a slightly different method. This avoided creating and calling functions:

    inp = input()     #to hold code text
    code = list(inp)  #store code as a list
    soln = []         #store the 'Goodness' for each of 26 possible answers
    y=0               #variable to hold total goodness during calculations
    clear = []        #will hold decoded text
    pos=0             #position marker for a list
    
    #for every possible value of shift
    #note range as 0 to 25 are valid shifts and shift 26 = shift 0
    
    for shift in range(0,26):
       for i in code:                  #loop through each letter in code
          if i == " ":                 #spaces have no score so omit them
             continue
          else:                        #if it's a letter
             x = ord(i)-shift          #apply the test shift
             if x < 65:                #prevent shifting outside A-Z range
                x = x + 26             
             x = x - 64                #turn ord into character position in A-Z with A=1
             x = letterGoodness[x-1]   #turn this into the Goodness score
             y = y + x                 #add this to a running total
       soln.insert(shift-1,y)          #AFTER decoding all letters in code, add total(y) to list of scores
       y = 0                           #reset y before next test value
    
    bestSoln=max(soln)                 #find highest possible score
    
    for i in range(0,26):              #check the list of solutions for this score
       if soln[i]==bestSoln:           #the position in this list is the shift we need
           bestShift = i+1             #+1 as the first solution is 0
    
    for i in code:                     #now decode the original text using our best solution
       if i == " ":                    #spaces are not encoded so just add these to the string
          clear.insert(pos," ")        #pos used to track next position for final string
          pos = pos + 1
          continue
       else:
          x = ord(i)-bestShift         #same operation as before
          if x < 65:
             x = x + 26
       z = chr(x)
       clear.insert(pos,z)             #add the decoded letter to the clear text
       pos = pos + 1
    print("".join(clear))              #join the list of clear text into one string and print it
    

    Note that many parts of this code could (and should) be compressed, for example

    x = x - 64
    x = letterGoodness[x-1]
    y = y + x
    

    They are left expanded to 'show my working' for a tutorial exercise.

    0 讨论(0)
  • 2021-01-03 06:15

    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!

    0 讨论(0)
  • 2021-01-03 06:31

    Here is my implementation which works fine.

    You should print the goodness of each possible message and see why your program output it.

    letterGoodness = dict(zip(string.ascii_uppercase,
                            [.0817,.0149,.0278,.0425,.1270,.0223,.0202,
                             .0609,.0697,.0015,.0077,.0402,.0241,.0675,
                             .0751,.0193,.0009,.0599,.0633,.0906,.0276,
                             .0098,.0236,.0015,.0197,.0007]))
    
    trans_tables = [ str.maketrans(string.ascii_uppercase,
                     string.ascii_uppercase[i:]+string.ascii_uppercase[:i])
                     for i in range(26)]
    
    def goodness(msg):
        return sum(letterGoodness.get(char, 0) for char in msg)
    
    def all_shifts(msg):
        msg = msg.upper()
        for trans_table in trans_tables:
            txt = msg.translate(trans_table)
            yield goodness(txt), txt
    
    print(max(all_shifts(input())))
    
    0 讨论(0)
提交回复
热议问题