Python. Взлом шифров. Продолжение-2.

На прошлом уроке мы написали функцию сопоставления слов. Сегодня продолжим эту тему. Допустим, у нас есть некий текст в котором нам надо найти место наилучше подходящее под это слово. Пишем вот такой код:

s="вапжуоваппробавапавпавпав"
i=0
w="проба"
min_res=999999999999999999999
min_word=""
while i<len(s)-len(w):
    j=0
    w1=""
    while j<len(w):
        w1=w1+s[i+j]
        j=j+1
    res=matching_word(w,w1)
    if res<min_res:
        min_res=res
        min_word=w1
    i=i+1

print("Минимальный результат "+str(min_res))
print("Найденное слово "+min_word)

Программа сообщит:

Минимальный результат 0
Найденное слово проба

Заменим в строке

s="вапжуоваппробавапавпавпав"

слово «проба» на слово «прога» и получим уже вот такой результат:

Минимальный результат 73
Найденное слово прога

Теперь попробуем поискать словом во всем файле:

f_matching = open("d:\9\match1.txt", "r") #файл с сопоставлением словарей
f_text = open("d:\9\some2.txt", "r") #файл с предобработанным текстом

dic={} #словарь

#Прочитаем файл сопоставлений и создадим словарь
for line in f_matching:
    ls=line.split("^")
    if len(ls)>2:
        c=ls[0]
        dic=ls[2]


ls=list(dic.items())


def search_simbol(s):    
    i=0
    while i<len(ls):
        if ls[i][0]==s:
            return i
        i=i+1
    return -1

def matching_word(w1,w2):
    i=0
    res=0
    while i<len(w1):
        dif=0
        if w1[i]!=w2[i]:
            ind1=search_simbol(w1[i])
            ind2=search_simbol(w2[i])
            if ind1==-1 or ind2==-1:
                dif=len(ls)+1
            else:
                dif=abs(ind1-ind2)
        res=res+dif
        i=i+1
    return res

#Прочитаем файл с предобработанным текстом и в каждой строке будем искать слово
w="Глава"
for s in f_text:    
    i=0    
    min_res=999999999999999999999
    min_word=""
    while i<len(s)-len(w):
        j=0
        w1=""
        while j<len(w):
            w1=w1+s[i+j]
            j=j+1
        res=matching_word(w,w1)
        if res<min_res:
            min_res=res
            min_word=w1
        if min_res==0:
            break
        i=i+1

print("Минимальный результат "+str(min_res))
print("Найденное слово "+min_word)

И тут я напоролся на грабли. Я специально привел код с ошибкой, чтобы рассказать об этих граблях. Итак, если вы запустите файл несколько раз, то каждый раз будете получать разные результаты! Сначала я не мог понять, почему так происходит. Затем выполнил вот такой код:

f_matching = open("d:\9\match1.txt", "r") #файл с сопоставлением словарей
f_text = open("d:\9\some2.txt", "r") #файл с предобработанным текстом

dic={} #словарь

#Прочитаем файл сопоставлений и создадим словарь - список
for line in f_matching:
    ls=line.split("^")
    if len(ls)>2:
        c=ls[0]
        dic=ls[2]


print(dic)

И увидел, что каждый раз порядок ключей в словаре разный.  Глюк можно исправить, если вместо словаря загружать буквы сразу в список:

f_matching = open("d:\9\match1.txt", "r") #файл с сопоставлением словарей
f_text = open("d:\9\some2.txt", "r") #файл с предобработанным текстом


#Прочитаем файл сопоставлений и создадим словарь - список
ls=[] #Создаем список
for line in f_matching:
    ls_line=line.split("^")
    if len(ls_line)>2:
        c=ls_line[0]
        ls.append(c)


def search_simbol(s):    
    i=0
    while i<len(ls):
        if ls[i]==s:
            return i
        i=i+1
    return -1


def matching_word(w1,w2):
    i=0
    res=0
    while i<len(w1):
        dif=0
        if w1[i]!=w2[i]:
            ind1=search_simbol(w1[i])
            ind2=search_simbol(w2[i])
            if ind1==-1 or ind2==-1:
                dif=len(ls)+1
            else:
                dif=abs(ind1-ind2)
        res=res+dif
        i=i+1
    return res


#Прочитаем файл с пробрбаботанным текстом и в каждой строке будем искать слово
word="Глава"
min_res=999999999999999999999
min_word=""
for s in f_text:    
    i=0    
    while i<len(s)-len(word):
        j=0
        word1=""
        while j<len(word):
            word1=word1+s[i+j]
            j=j+1
        res=matching_word(word,word1)
        if res<min_res:
            min_res=res
            min_word=word1
            print(min_word+" "+str(min_res))
        if min_res==0:
            break
        i=i+1

print("Минимальный результат "+str(min_res))
print("Найденное слово "+min_word)

f_text.close()

Теперь можно подставлять слова из полученного на предыдущем этапе списка слов, начиная с верха списка, где у нас наиболее часто встречающиеся слова. Например, нас слово «Глава» у меня выдало вот такой результат:

Минимальный результат 29
Найденное слово кзала

На слово «Девушка» вот такой:

Минимальный результат 73
Найденное слово девушка

А вот такие слова как «как», «что» уже присутствуют в расшифрованном виде, то есть, по ним выдало, что расхождение 0.

Такой поиск ничего не дал, поэтому попробуем альтернативный вариант, который мы отвергли вначале: смотреть только по количеству различных букв.

Тогда функция сопоставления слов будет выглядеть вот так:

def matching_word_v2(w1,w2):
    i=0
    res=0
    while i<len(w1):
        dif=0
        if w1[i]!=w2[i]:
            dif=dif+1
        res=res+dif
        i=i+1
    return res

Теперь попробуем точно также поискать слово «Глава». Находим «става». Но, как оказалось, это всего лишь часть слова «оставалось»:

Так идем, проверяя все слова из списка. На слове «Сначала» мы находим слово «фначала». Это что-то уже похожее на правду. Смотрим:

Сразу видим, что кроме замены «С» <-> «ф», можно сделать замены «ж» <-> «х», а также «б» <-> «.»

И получаем уже вот такой выходной результат:

Как видим, задача полной автоматизации расшифровки текста, даже самого простого, далеко не тривиальна. Но, в полуручном-полуавтоматическом режиме она решаема. Для автоматизации тех подходов, которые мы изучили в данном цикле уроком, необходимо освоить различные примеры работы с текстом, чем мы с вами займемся в будущих уроках.

 

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar