Вася любит секреты и шифрование. Он часто пользуется шифром на основе замен и просит разработать вас функцию, которая позволит ему быстро шифровать сообщения.
Напишите функцию 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')))
Посмотреть код
Решение
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
Решение
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
Решение
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
Решение
# Пример кода с ошибкой, который проходит тесты.
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