J. Ключевой секрет

Вася любит секреты и шифрование. Он часто пользуется шифром на основе замен и просит разработать вас функцию, которая позволит ему быстро шифровать сообщения.

Напишите функцию secret_replace, которая принимает:

  • текст требующий шифрования;
  • именованные аргументы — правила замен, представляющие собой кортежи из одного или нескольких значений.

Функция должна вернуть зашифрованный текст.

Примечание

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

Пример

Ввод

result = secret_replace("Hello, world!", l=("hi", "y"), o=("123", "z"))

Вывод

result = 'Hehiy123, wzrhid!'

Ввод

result = secret_replace(
    "ABRA-KADABRA",
    A=("Z", "1", "!"),
    B=("3",),
    R=("X", "7"),
    K=("G", "H"),
    D=("0", "2"),
)

Вывод

result = 'Z3X1-G!0Z371'

Решение

Задача не сильно сложная с одной стороны. С другой стороны я не знаю ни одного решения, которое бы полностью меня устроило. Каждое из предлагаемых решений проходит проверку, но каждое из них имеет недостаток.

Первое не очень элегантно, но бережно относится к входным данным.

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

Третье решение базируется на втором, но предполагает использование cycle из itertools, который мы изучили ранее.

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

Ошибка в тесте Яндекса

Задача плохо покрыта тестами и по состоянию на 29-11-2023 позволяет пройти тест коду, который зацикливается на таком вызове:

print(secret_replace('a', a=('aa', 'aaa')))

Посмотреть код

Решение

Python
def secret_replace(text, **secrets):
    new_text = ''
    secrets = {key: [value, 0] for key, value in secrets.items()}
    for char in text:
        if char in secrets:
            pos = secrets[char][1] % len(secrets[char][0])
            new_text += secrets[char][0][pos]
            secrets[char] = [secrets[char][0], pos + 1]
        else:
            new_text += char
    return new_text

Решение

Python
def secret_replace(text, **code):
    new_text = ''
    for char in text:
        if char in code:
            new_text += code[char][0]
            code[char] = code[char][1:] + (code[char][0],)
        else:
            new_text += char
    return new_text

Решение

Python
from itertools import cycle


def secret_replace(text, **code):
    new_text = ''
    cycled_code = {char: cycle(replacements) for char, replacements in code.items()}
    for char in text:
        if char in cycled_code:
            new_text += next(cycled_code[char])
        else:
            new_text += char

    return new_text

Решение

Python
# Пример кода с ошибкой, который проходит тесты.

def secret_replace(text, **code):
    for item in code:
        while item in text:
            for substitution in code[item]:
                if item in text:
                    text = text[:text.find(item)] + substitution + text[text.find(item) + 1:]
    return text
Подписаться
Уведомить о
guest
15 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии