0

I'm trying to do a caesar cipher and here is my code

def getinputfile(message):
    list_ = []
    with open(message, 'r') as lines:
        content = lines.readlines()
    
    for i in content:
        list_.append(i.strip())
    
    return list_
    
def decrpyt(list_):
    decrypt_num = []
    decrypt_list = []    
    sec_message = list_[1]
    sec_key = int(list_[0])
    
    for letter in sec_message :
        uni_num = (ord(letter) - sec_key) 
        decrypt_num.append(uni_num)
    
    for unicode in decrypt_num:
        uni_letter = chr(unicode)
        decrypt_list.append(uni_letter)    
    return decrypt_list

def main():
    message = getinputfile('secretMessage1.txt')
    decrpyted_message = decrpyt(message)
    print(''.join(decrpyted_message))
main()

The output that I got is CU4GXA:;2a:/54Y and I want congratulations. Now I sort of realize the problem and that is the ASCII code for all the lower case letters in the alphabet is only from 97 - 122 and whenever I subtract the key from the ord of the letters, it goes beyond 97 and 122.

I tried solving this using % (I'm not 100% sure as to how to use the modulo operator as well) but I wasn't successful in doing so.

The contents of the text file are:

18

UgFYjSLMDsLAGFk
tripleee
  • 175,061
  • 34
  • 275
  • 318
boyboy_290
  • 37
  • 4
  • I don't see the `%` in the code you posted. You probably want `% 256` or `% 128`. – Mark Ransom Jan 29 '21 at 06:01
  • First search hit is https://stackoverflow.com/questions/53886402/how-do-i-use-modulo-arithmetic-to-implement-caesar-cipher, it's for [tag:c] but you can probably make sense of it. – tripleee Jan 29 '21 at 06:05

1 Answers1

0

Shift each letter so that the alphabet you're rotating maps to 0-25, apply the transformation, do % 26, and then shift it back.

>>> def decrypt(message: str, key: int) -> str:
...     def decrypt_letter(letter: str) -> str:
...         alpha = ord('a' if letter.islower() else 'A')
...         return chr((ord(letter) - alpha - key) % 26 + alpha)
...     return ''.join(decrypt_letter(c) for c in message)
...
>>> with open('secretMessage1.txt') as file:
...     key, message = file.readlines()
...     print(decrypt(message.strip(), int(key.strip())))
...
CoNGrATULaTIONs

(edit) If your output doesn't actually need to preserve case, the decrypt function becomes much simpler -- just lowercase the message and then you can ignore the islower() check.

>>> def decrypt(message: str, key: int) -> str:
...     return ''.join(
...         chr((ord(c) - ord('a') - key) % 26 + ord('a'))
...         for c in message.lower()
...     )
...
>>> decrypt("UgFYjSLMDsLAGFk", 18)
'congratulations'
Samwise
  • 68,105
  • 3
  • 30
  • 44
  • Oh sorry I think I left out an important detail and that is, the output has to be all lower case letters. – boyboy_290 Jan 29 '21 at 18:06
  • That important detail makes the solution quite a bit easier, lol – Samwise Jan 29 '21 at 18:40
  • how do would you take into account the spaces in the text – boyboy_290 Jan 30 '21 at 02:08
  • Look at the first solution I posted -- see how there's a `decrypt_letter` function that handles different letters different ways? You could have that function check to see if something's not a letter at all and just return it unmodified. – Samwise Jan 30 '21 at 16:21