1 """A set of ciphers with implementations for both enciphering and deciphering
2 them. See cipherbreak for automatic breaking of these ciphers
8 from itertools
import zip_longest
, cycle
, chain
9 from language_models
import unaccent
, sanitise
12 def caesar_encipher_letter(accented_letter
, shift
):
13 """Encipher a letter, given a shift amount
15 >>> caesar_encipher_letter('a', 1)
17 >>> caesar_encipher_letter('a', 2)
19 >>> caesar_encipher_letter('b', 2)
21 >>> caesar_encipher_letter('x', 2)
23 >>> caesar_encipher_letter('y', 2)
25 >>> caesar_encipher_letter('z', 2)
27 >>> caesar_encipher_letter('z', -1)
29 >>> caesar_encipher_letter('a', -1)
31 >>> caesar_encipher_letter('A', 1)
33 >>> caesar_encipher_letter('é', 1)
36 letter
= unaccent(accented_letter
)
37 if letter
in string
.ascii_letters
:
38 if letter
in string
.ascii_uppercase
:
39 alphabet_start
= ord('A')
41 alphabet_start
= ord('a')
42 return chr(((ord(letter
) - alphabet_start
+ shift
) % 26) +
47 def caesar_decipher_letter(letter
, shift
):
48 """Decipher a letter, given a shift amount
50 >>> caesar_decipher_letter('b', 1)
52 >>> caesar_decipher_letter('b', 2)
55 return caesar_encipher_letter(letter
, -shift
)
57 def caesar_encipher(message
, shift
):
58 """Encipher a message with the Caesar cipher of given shift
60 >>> caesar_encipher('abc', 1)
62 >>> caesar_encipher('abc', 2)
64 >>> caesar_encipher('abcxyz', 2)
66 >>> caesar_encipher('ab cx yz', 2)
68 >>> caesar_encipher('Héllo World!', 2)
71 enciphered
= [caesar_encipher_letter(l
, shift
) for l
in message
]
72 return ''.join(enciphered
)
74 def caesar_decipher(message
, shift
):
75 """Decipher a message with the Caesar cipher of given shift
77 >>> caesar_decipher('bcd', 1)
79 >>> caesar_decipher('cde', 2)
81 >>> caesar_decipher('cd ez ab', 2)
83 >>> caesar_decipher('Jgnnq Yqtnf!', 2)
86 return caesar_encipher(message
, -shift
)
89 if __name__
== "__main__":