2015-06-03 2 views
0

У меня есть строка, которая была зашифрована в моно-алфавитном подстановке, я хотел попробовать и взломать ее, используя частотный анализ английского языка (а не на самом деле его решить, но чтобы обогатить мои навыки программирования).Подставляйте все буквы в строку

Я в настоящее время в ситуации, когда у меня есть частоты букв появлений в строке, представленной в отсортированном списке tuple с, например, следующее: [('V', freqV), ('D', freqD)...] (обратите внимание, что в данном случае V это письмо, которое появляется больше, чем любая другая буква, поэтому freqV - это наибольшее число, отображаемое в tuple s, которые указаны в списке), а также английский язык представлен таким же образом.

Из этого состояния, как правильно заменить буквы?

Я уже попробовал простой лобовое решение:

new_text = str(cipher_str) 

for i in xrange(26): #26 is the length of both lists, obviously 
    new_text = new_text.replace(sorted_cipher_freq[i][0], sorted_eng_freq[i][0]) 

, но он не будет работать (одна из причин в том, что иногда персонаж заменить с идентичен расшифрованного один. Например, ap = an, так что буква a такая же, что и при дешифровке и зашифровке, но p должно быть n).

Как я могу это сделать?

+2

Одна из проблем, которые вы собираетесь работать в вашей реализации является то, что вы изменяете литий пока вы пытаетесь перебрать его. Это приведет к тому, что ваши подмены будут угасать, потому что, например, после первых нескольких вы заменяете буквы, которые уже являются подслоями. Вместо этого вы создаете сопоставление (read: dict) подстановок, затем перебираете кодированную строку, создавая новую строку по одному символу за раз с отображением. –

+0

@ Two-BitAlchemist Но это испортит порядок букв ... Итак, я должен уже сдаться и пойти со словарем '{letter_in_cipher: letter_to_sub_with}'? – Jack

ответ

2

вы бы его и использовать самую высокую частоту и сопоставить его с самой высокой частотой N ... что-то вроде этого

en_freq="ETAOINSHDLUCMFYWGPBVKXQJZ" #from http://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html 
encoded_text =open("encrypted.txt").read().upper()#normalize to uppercase 
sorted_my_frequency = Counter(encoded_text).most_frequent(len(en_freq)) #we want the 25 most frequent characters (sorted 
my_frequency=join(sorted_my_frequency)[:len(en_freq)] 

translation_table = string.maketrans(my_frequency,en_freq) #map our most frequent to expected english frequencies 

print encoded_text.translate(translation_table) #apply the translation_table 
#note that you need a fairly large ammount of text for this to work very well ... and you will likely still need to manually translate some parts 

отмечают, что могут быть некоторые незначительные ошибки, как я на самом деле не запускать это или иметь какой-либо целевой текст для декодирования

+0

Спасибо, именно то, что я искал. Никогда не знал «Counter» до сих пор ... – Jack

0

Возможны попробовать сделать это посимвольно:

sorted_cipher_freq = [('V', 25), ('D', 10)] 
simple_cipher_freq = [letter for letter, freq in sorted_cipher_freq] 

en_freq="ETAOINSHDLUCMFYWGPBVKXQJZ" 

new_text = '' 
for char in cipher_str: 
    new_char = en_freq[simple_cipher_freq.index(char)] 
    new_text += new_char 

print new_text 
Смежные вопросы