1 """A set of ciphers with implementations for both enciphering and deciphering
2 them. See cipherbreak for automatic breaking of these ciphers
7 # from enum import Enum
8 # from itertools import zip_longest, cycle, chain
10 from language_models
import unaccent
, sanitise
13 def caesar_encipher_letter(accented_letter
, shift
):
14 """Encipher a letter, given a shift amount
16 >>> caesar_encipher_letter('a', 1)
18 >>> caesar_encipher_letter('a', 2)
20 >>> caesar_encipher_letter('b', 2)
22 >>> caesar_encipher_letter('x', 2)
24 >>> caesar_encipher_letter('y', 2)
26 >>> caesar_encipher_letter('z', 2)
28 >>> caesar_encipher_letter('z', -1)
30 >>> caesar_encipher_letter('a', -1)
32 >>> caesar_encipher_letter('A', 1)
34 >>> caesar_encipher_letter('é', 1)
37 letter
= unaccent(accented_letter
)
38 if letter
in string
.ascii_letters
:
39 if letter
in string
.ascii_uppercase
:
40 alphabet_start
= ord('A')
42 alphabet_start
= ord('a')
43 return chr(((ord(letter
) - alphabet_start
+ shift
) % 26) +
48 def caesar_decipher_letter(letter
, shift
):
49 """Decipher a letter, given a shift amount
51 >>> caesar_decipher_letter('b', 1)
53 >>> caesar_decipher_letter('b', 2)
56 return caesar_encipher_letter(letter
, -shift
)
58 def caesar_encipher(message
, shift
):
59 """Encipher a message with the Caesar cipher of given shift
61 >>> caesar_encipher('abc', 1)
63 >>> caesar_encipher('abc', 2)
65 >>> caesar_encipher('abcxyz', 2)
67 >>> caesar_encipher('ab cx yz', 2)
69 >>> caesar_encipher('Héllo World!', 2)
72 enciphered
= [caesar_encipher_letter(l
, shift
) for l
in message
]
73 return ''.join(enciphered
)
75 def caesar_decipher(message
, shift
):
76 """Decipher a message with the Caesar cipher of given shift
78 >>> caesar_decipher('bcd', 1)
80 >>> caesar_decipher('cde', 2)
82 >>> caesar_decipher('cd ez ab', 2)
84 >>> caesar_decipher('Jgnnq Yqtnf!', 2)
87 return caesar_encipher(message
, -shift
)
90 if __name__
== "__main__":