Пітон 3, 423 байти
import sys,re
S=re.sub
D,*L=sys.stdin.read().split('\n')
def f(W,M=[],V="",r=0):
if len({d for(s,d)in M})==len(M):
if[]==W:return V.lower()
for d in D.split():p='([a-z])(?%s.*\\1)';m=re.match(S(p%'=',')\\1=P?(',S(p%'!',').>\\1<P?(',W[0].translate(dict(M))[::-1]))[::-1]+'$',d.upper());r=r or m and f(W[1:],M+[(ord(s),m.group(s))for s in m.groupdict()],V+d+" ")
return r
for l in L:print(f(l.split())or S('\w','*',l))
Читає вхід зі STDIN і записує вихід у STDOUT, використовуючи той же формат, що і зразок вводу / виводу.
Пояснення
Для кожного рядка шифротексту виконуємо таку процедуру:
Ми зберігаємо карту, М , усіх уже встановлених буквених перетворень (які спочатку порожні). Ми робимо це так, щоб літери-вихідні літери були малими літерами, а літери призначення - великими літерами.
Обробляємо слова в шифротексті по порядку. Для кожного слова ми знаходимо всі слова у словнику, з якими він може відповідати:
Припустимо, що наше слово, w , є glpplppljjlі що M містить правило j -> P. Спочатку перетворюємо w, використовуючи існуючі правила в M , отримуючи glpplpplPPl. Потім ми перетворюємо w у наступний з ароматом пітон:
(?P<g>.)(?P<l>.)(?P<p>.)(?P=p)(?P=l)(?P=p)(?P=p)(?P=l)PP(?P=l)
Правила перетворення такі:
- Перше виникнення кожної малої літери,
xзамінюється на . Це визначає іменовану групу захоплення, що називається , що відповідає одному cahracter.(?P<x>.)x
- Кожне наступне виникнення кожної малої літери,
xзамінюється на . Це зворотне відношення до персонажа, попередньо захопленого названою групою .(?P=x)x
Ми виконуємо це перетворення шляхом реверсування w , потім застосовуючи дві наступні заміни регулярних виразів:
s/([a-z])(?!.*\1)/)>\1<P?(/
s/([a-z])(?=.*\1)/)\1=P?(/
а потім реверсувати результат. Зауважте, що символи, які раніше були трансформовані M, виглядають як великі, і тому залишаються незмінними.
Отриманий регекс ми співставляємо з кожним зі словникових слів, де слова словника відображаються як великі регістри. Наприклад, вищевказаний регулярний вираз відповідатиме слову MISSISSIPPI. Якщо ми знаходимо матч, ми здобуваємо нові правила перетворення з нього, і додати їх в M . Нові правила перетворення - це просто символи, захоплені кожною із груп захоплення. У вищевказаному регексі, групові gматчі M, груповий lматч Iта групові pпоєдинки S, що дає нам правила g -> M, l -> I, p -> S. Ми повинні переконатись у тому, що отримані правила є послідовними, тобто, що жодні два вихідні літери не відображаються в одній і тій же літері призначення; в іншому випадку ми відхиляємо відповідність.
Потім переходимо до наступного слова, використовуючи правила розширеного перетворення. Якщо ми можемо зіставити всі слова шифротексту за допомогою цього процесу, ми розшифрували текст. Якщо ми не можемо зіставити слово проти жодного зі словникових слів, ми відхиляємось і намагаємося співставити попередні слова з різними словниковими словами. Якщо цей процес не вдався, рішення немає, і ми друкуємо ряд зірочок.