Криптичний кікер //


12

Криптичний кікер

Поширений, але небезпечний метод шифрування тексту - перестановка літер алфавіту. Іншими словами, кожна літера алфавіту послідовно замінюється в тексті якоюсь іншою літерою. Щоб переконатися, що шифрування є оборотним, жодна літера не замінюється на одну і ту ж букву. Ваше завдання - розшифрувати кілька закодованих рядків тексту, припускаючи, що кожен рядок використовує різний набір замін і що всі слова в розшифрованому тексті є зі словника відомих слів.

Вхідні дані

Вхід складається з малих слів, в алфавітному порядку. Ці слова складають словник слів, які можуть з’явитися в розшифрованому тексті. Слідом за словником є ​​кілька рядків введення. Кожен рядок шифрується, як описано вище.

У словнику не більше 1000 слів. Жодне слово не перевищує 16 літер. Зашифровані рядки містять лише малі літери та пробіли і не перевищують 80 символів.

Вихідні дані

Розшифруйте кожен рядок і роздрукуйте його до стандартного виводу. Якщо є кілька рішень, будь-яке зробить. Якщо рішення немає, замініть кожну букву алфавіту зірочкою.

Зразок введення

and dick jane puff spot yertle

bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd

Вибірка зразка

dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ******

Ось рішення. Зверніть увагу, що я не кінь, що біжить у гонці за найкоротші байти / Конкурентний програміст. Мені просто подобаються пазли!

( Джерело )


1
Будь ласка, розслабте свої> вхідні <обмеження щодо того, що стосується кожної мови. Наприклад, багато мов будуть ненавидіти, а не оцінюватимуть, що формат починається з 6. Я б запропонував залишити формат зовсім не визначеним, і я лише скажу, що введення - це список слів та список рядків для шифрування.
orlp

Гаразд, ось ти!
Dhruv Ramani

1
Чи є для цього обмеження часу виконання? Чи можу я просто переглядати всі можливі комбінації заміни, поки не вийде одна робота (на що, швидше за все, знадобляться роки)?
Натан Меррілл

@NathanMerrill Зробіть це, і якщо це займе роки, просто надрукуйте це у формі зірки. Віхан, це не дублікат, будь ласка, прочитайте питання належним чином.
Друв Рамані

Чи можемо ми просто вивести слова або нам до них приєднатися?
Downgoat

Відповіді:


3

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

Потім переходимо до наступного слова, використовуючи правила розширеного перетворення. Якщо ми можемо зіставити всі слова шифротексту за допомогою цього процесу, ми розшифрували текст. Якщо ми не можемо зіставити слово проти жодного зі словникових слів, ми відхиляємось і намагаємося співставити попередні слова з різними словниковими словами. Якщо цей процес не вдався, рішення немає, і ми друкуємо ряд зірочок.


2

CJam, 62 56 байт

qN%Sf/(f{\:C,m*{C..+`Sa`m2/Q|z_''f-Qf|=},C:,'*f*a+0=S*N}

Досить повільно і голодна пам'ять, але працює для тестового випадку з інтерпретатором Java.

Приклад виконання

$ cat input; echo
and dick jane puff spot yertle

bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd
$ time cjam kicker.cjam < input
dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ******

real    5m19.817s
user    6m41.740s
sys     0m1.611s
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.