Пітон 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
. Ми повинні переконатись у тому, що отримані правила є послідовними, тобто, що жодні два вихідні літери не відображаються в одній і тій же літері призначення; в іншому випадку ми відхиляємо відповідність.
Потім переходимо до наступного слова, використовуючи правила розширеного перетворення. Якщо ми можемо зіставити всі слова шифротексту за допомогою цього процесу, ми розшифрували текст. Якщо ми не можемо зіставити слово проти жодного зі словникових слів, ми відхиляємось і намагаємося співставити попередні слова з різними словниковими словами. Якщо цей процес не вдався, рішення немає, і ми друкуємо ряд зірочок.