Сказки из склепа

Советы и хитрости Pythonic - Основы криптографии

Использование Python для расшифровки закодированных сообщений

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

Получение суммы всех цифр целого числа

Скажем, вопрос был в следующем:

«Получите сумму всех цифр целого числа, сделайте решение достаточно обобщаемым, чтобы работать с любым целым числом»

Предполагая, что число, данное нам как целое число, мы можем просто преобразовать его в строку, а затем просто использовать функцию разделения, чтобы получить список цифр. Все, что нам нужно сделать, это использовать функцию sum.

def digit_sum_v1(number):
    number = [c for c in str(number)]
    return sum(number)
    
digit_sum_v1(369)

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

Мы видим, что все элементы списка на самом деле являются строками. Это означает, что для исправления нашей функции нам просто нужно преобразовать каждый элемент списка в целое число, прежде чем мы активируем функцию суммы.

def digit_sum_v1(number):
    number = [int(c) for c in str(number)]
    return sum(number)
digit_sum_v1(369)

Отлично, наша функция делает именно то, что мы хотим. Давай проверим вменяемость.

Вроде все хорошо. Это было довольно простое упражнение, давайте немного усложним его.

Получение суммы всех цифр в целом числе с использованием логики If-Else

Скажем, вопрос был в следующем:

«Получите сумму всех четных цифр и произведение всех нечетных цифр в виде целого числа. Если целое число больше 5000, получите вместо этого произведение всех четных цифр и сумму всех нечетных цифр. Сделайте решение достаточно универсальным, чтобы работать с любым целым числом »

Уф, это действительно стало намного сложнее. На самом деле это было бы ближе к тому, что требовалось бы от специалиста по данным, чем простая функция суммирования цифр. Итак, давайте решим эту задачу.

from numpy import prod
def digit_sum_v2(number):
    digit_even = [int(c) for c in str(number) if (int(c)%2 == 0)]
    digit_odd = [int(c) for c in str(number) if (int(c)%2 != 0)]
    
    if number > 5000:
        even = prod(digit_even)
        odd = sum(digit_odd)
    else:
        even = sum(digit_even)
        odd = prod(digit_odd)
    return even, odd

Обратите внимание, что нам пришлось использовать функцию prod из NumPy. По сути, мы создаем два разных списка, один из которых заполнен всеми четными цифрами, а другой - всеми нечетными цифрами. Затем мы вводим в действие функции sum и prod в соответствии с размером целого числа.

Давайте прогоним нашу функцию через несколько целых чисел и посмотрим, дает ли она нам то, что мы хотим.

print(digit_sum_v2(1212))
print(digit_sum_v2(1313))
print(digit_sum_v2(3131))
print(digit_sum_v2(1515))
print(digit_sum_v2(5151))

Отлично, наша функция работает, как задумано. Обратите внимание, что особенностью нашей функции является то, что она не зависит от положения цифр. Это означает, что числа с одинаковыми цифрами должны давать одинаковые результаты, ЕСЛИ, конечно, одно из них не превышает 5000.

Теперь вы можете спросить себя, какое отношение это имеет к закодированным сообщениям? Что ж, давайте еще раз усложним этот последний вопрос.

«Получите сумму всех цифр, равных или меньших 5, и произведение всех цифр, превышающих 5 в виде целого числа. Если целое число больше 5000, получите вместо этого произведение всех цифр, равных или меньших 5, и суммы всех цифр, превышающих 5.

Сопоставьте результаты с Alphabet DataFrame с помощью приведенной ниже логики:

Вывод Ниже 5 индексирует строки фреймов данных.

Вывод выше 5 индексирует столбцы фреймов данных.

Оба выходных индекса через DataFrame циклически

Вам следует использовать только одну функцию, которая будет принимать в качестве входных данных список целых чисел и Alphabet DataFrame ».

import numpy as np
import pandas as pd
alphabet_matrix = pd.DataFrame(np.array(list('abcdefghijklmnñopqrstuvwxyz_'))
             .reshape(4,7))
alphabet_matrix

Обратите внимание, что в этом упражнении подчеркивание будет обозначать пробел. Хорошо, давайте решим эту проблему.

def decoder(list_of_ints, df_reference):
    references = []
    for i in list_of_ints:
        below_5 = [int(c) for c in str(i) if (int(c) <= 5)]
        above_5 = [int(c) for c in str(i) if (int(c) > 5)]
        if i > 5000:
            bel_5 = prod(below_5)
            abv_5 = sum(above_5)
        else:
            bel_5 = sum(below_5)
            abv_5 = prod(above_5)
        references.append((bel_5, abv_5))
        
    final_message = [df_reference
                    [r[1]%(df_reference.shape[1])]
                    [r[0]%(df_reference.shape[0])]
                    for r in references]
        
    return ' '.join(final_message)

Давайте запустим функцию и посмотрим, что за скрытое сообщение.

message = decoder([1080, 1116, 1099, 1108, 1280, 9904, 1611, 119, 2199, 561, 17, 181, 61], alphabet_matrix)
print(message)

В заключение

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