4d9a7220320067d372e53275011c4d1a8283ec44
1 from utilities
import *
2 from language_models
import *
3 from logger
import logger
5 def caesar_encipher_letter(accented_letter
, shift
):
6 """Encipher a letter, given a shift amount
8 >>> caesar_encipher_letter('a', 1)
10 >>> caesar_encipher_letter('a', 2)
12 >>> caesar_encipher_letter('b', 2)
14 >>> caesar_encipher_letter('x', 2)
16 >>> caesar_encipher_letter('y', 2)
18 >>> caesar_encipher_letter('z', 2)
20 >>> caesar_encipher_letter('z', -1)
22 >>> caesar_encipher_letter('a', -1)
24 >>> caesar_encipher_letter('A', 1)
26 >>> caesar_encipher_letter('é', 1)
29 # letter = unaccent(accented_letter)
30 # if letter in string.ascii_letters:
31 # if letter in string.ascii_uppercase:
32 # alphabet_start = ord('A')
34 # alphabet_start = ord('a')
35 # return chr(((ord(letter) - alphabet_start + shift) % 26) +
40 letter
= unaccent(accented_letter
)
41 if letter
in string
.ascii_letters
:
42 cipherletter
= unpos(pos(letter
) + shift
)
43 if letter
in string
.ascii_uppercase
:
44 return cipherletter
.upper()
50 def caesar_decipher_letter(letter
, shift
):
51 """Decipher a letter, given a shift amount
53 >>> caesar_decipher_letter('b', 1)
55 >>> caesar_decipher_letter('b', 2)
58 return caesar_encipher_letter(letter
, -shift
)
60 def caesar_encipher(message
, shift
):
61 """Encipher a message with the Caesar cipher of given shift
63 >>> caesar_encipher('abc', 1)
65 >>> caesar_encipher('abc', 2)
67 >>> caesar_encipher('abcxyz', 2)
69 >>> caesar_encipher('ab cx yz', 2)
71 >>> caesar_encipher('Héllo World!', 2)
74 enciphered
= [caesar_encipher_letter(l
, shift
) for l
in message
]
75 return cat(enciphered
)
77 def caesar_decipher(message
, shift
):
78 """Decipher a message with the Caesar cipher of given shift
80 >>> caesar_decipher('bcd', 1)
82 >>> caesar_decipher('cde', 2)
84 >>> caesar_decipher('cd ez ab', 2)
86 >>> caesar_decipher('Jgnnq Yqtnf!', 2)
89 return caesar_encipher(message
, -shift
)
92 def caesar_break(message
, fitness
=Pletters
):
93 """Breaks a Caesar cipher using frequency analysis
95 >>> caesar_break('ibxcsyorsaqcheyklxivoexlevmrimwxsfiqevvmihrsasrxliwyrh' \
96 'ecjsppsamrkwleppfmergefifvmhixscsymjcsyqeoixlm') # doctest: +ELLIPSIS
97 (4, -130.849989015...)
98 >>> caesar_break('wxwmaxdgheetgwuxztgptedbgznitgwwhpguxyhkxbmhvvtlbhgtee' \
99 'raxlmhiixweblmxgxwmhmaxybkbgztgwztsxwbgmxgmert') # doctest: +ELLIPSIS
100 (19, -128.82410410...)
101 >>> caesar_break('yltbbqnqnzvguvaxurorgenafsbezqvagbnornfgsbevpnaabjurer' \
102 'svaquvzyvxrnznazlybequrvfohgriraabjtbaruraprur') # doctest: +ELLIPSIS
103 (13, -126.25403935...)
105 sanitised_message
= sanitise(message
)
107 best_fit
= float('-inf')
108 for shift
in range(26):
109 plaintext
= caesar_decipher(sanitised_message
, shift
)
110 fit
= fitness(plaintext
)
111 logger
.debug('Caesar break attempt using key {0} gives fit of {1} '
112 'and decrypt starting: {2}'.format(shift
, fit
,
117 logger
.info('Caesar break best fit: key {0} gives fit of {1} and '
118 'decrypt starting: {2}'.format(best_shift
, best_fit
,
119 caesar_decipher(sanitised_message
, best_shift
)[:50]))
120 return best_shift
, best_fit