1 from support
.utilities
import *
2 from support
.language_models
import *
4 from logger
import logger
6 def caesar_encipher_letter(accented_letter
, shift
):
7 """Encipher a letter, given a shift amount
9 >>> caesar_encipher_letter('a', 1)
11 >>> caesar_encipher_letter('a', 2)
13 >>> caesar_encipher_letter('b', 2)
15 >>> caesar_encipher_letter('x', 2)
17 >>> caesar_encipher_letter('y', 2)
19 >>> caesar_encipher_letter('z', 2)
21 >>> caesar_encipher_letter('z', -1)
23 >>> caesar_encipher_letter('a', -1)
25 >>> caesar_encipher_letter('A', 1)
27 >>> caesar_encipher_letter('é', 1)
30 # letter = unaccent(accented_letter)
31 # if letter in string.ascii_letters:
32 # if letter in string.ascii_uppercase:
33 # alphabet_start = ord('A')
35 # alphabet_start = ord('a')
36 # return chr(((ord(letter) - alphabet_start + shift) % 26) +
41 letter
= unaccent(accented_letter
)
42 if letter
in string
.ascii_letters
:
43 cipherletter
= unpos(pos(letter
) + shift
)
44 if letter
in string
.ascii_uppercase
:
45 return cipherletter
.upper()
51 def caesar_decipher_letter(letter
, shift
):
52 """Decipher a letter, given a shift amount
54 >>> caesar_decipher_letter('b', 1)
56 >>> caesar_decipher_letter('b', 2)
59 return caesar_encipher_letter(letter
, -shift
)
61 def caesar_encipher(message
, shift
):
62 """Encipher a message with the Caesar cipher of given shift
64 >>> caesar_encipher('abc', 1)
66 >>> caesar_encipher('abc', 2)
68 >>> caesar_encipher('abcxyz', 2)
70 >>> caesar_encipher('ab cx yz', 2)
72 >>> caesar_encipher('Héllo World!', 2)
75 enciphered
= [caesar_encipher_letter(l
, shift
) for l
in message
]
76 return cat(enciphered
)
78 def caesar_decipher(message
, shift
):
79 """Decipher a message with the Caesar cipher of given shift
81 >>> caesar_decipher('bcd', 1)
83 >>> caesar_decipher('cde', 2)
85 >>> caesar_decipher('cd ez ab', 2)
87 >>> caesar_decipher('Jgnnq Yqtnf!', 2)
90 return caesar_encipher(message
, -shift
)
93 def caesar_break(message
, fitness
=Pletters
):
94 """Breaks a Caesar cipher using frequency analysis
96 >>> caesar_break('ibxcsyorsaqcheyklxivoexlevmrimwxsfiqevvmihrsasrxliwyrh' \
97 'ecjsppsamrkwleppfmergefifvmhixscsymjcsyqeoixlm') # doctest: +ELLIPSIS
98 (4, -130.849989015...)
99 >>> caesar_break('wxwmaxdgheetgwuxztgptedbgznitgwwhpguxyhkxbmhvvtlbhgtee' \
100 'raxlmhiixweblmxgxwmhmaxybkbgztgwztsxwbgmxgmert') # doctest: +ELLIPSIS
101 (19, -128.82410410...)
102 >>> caesar_break('yltbbqnqnzvguvaxurorgenafsbezqvagbnornfgsbevpnaabjurer' \
103 'svaquvzyvxrnznazlybequrvfohgriraabjtbaruraprur') # doctest: +ELLIPSIS
104 (13, -126.25403935...)
106 sanitised_message
= sanitise(message
)
108 best_fit
= float('-inf')
109 for shift
in range(26):
110 plaintext
= caesar_decipher(sanitised_message
, shift
)
111 fit
= fitness(plaintext
)
112 logger
.debug('Caesar break attempt using key {0} gives fit of {1} '
113 'and decrypt starting: {2}'.format(shift
, fit
,
118 logger
.info('Caesar break best fit: key {0} gives fit of {1} and '
119 'decrypt starting: {2}'.format(best_shift
, best_fit
,
120 caesar_decipher(sanitised_message
, best_shift
)[:50]))
121 return best_shift
, best_fit