Cryptic Kicker
Powszechną, ale niepewną metodą szyfrowania tekstu jest permutacja liter alfabetu. Innymi słowy, każda litera alfabetu jest konsekwentnie zastępowana w tekście inną literą. Aby zapewnić odwracalność szyfrowania, dwie litery nie są zastępowane tą samą literą. Twoim zadaniem jest odszyfrowanie kilku zakodowanych wierszy tekstu, przy założeniu, że każda linia używa innego zestawu zamienników i że wszystkie słowa w odszyfrowanym tekście pochodzą ze słownika znanych słów.
Wejście
Dane wejściowe składają się z małych liter w kolejności alfabetycznej. Te słowa składają się na słownik słów, które mogą pojawić się w odszyfrowanym tekście. Po słowniku znajduje się kilka wierszy wprowadzania. Każda linia jest szyfrowana zgodnie z powyższym opisem.
Słownik nie zawiera więcej niż 1000 słów. Żadne słowo nie przekracza 16 liter. Zaszyfrowane linie zawierają tylko małe litery i spacje i nie przekraczają 80 znaków.
Wynik
Odszyfruj każdą linię i wydrukuj ją na standardowe wyjście. Jeśli istnieje wiele rozwiązań, każde z nich zrobi. Jeśli nie ma rozwiązania, zastąp każdą literę alfabetu gwiazdką.
Przykładowe dane wejściowe
and dick jane puff spot yertle
bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd
Przykładowe dane wyjściowe
dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ******
Oto rozwiązanie. Należy pamiętać, że nie jestem koniem biegnącym w wyścigu o najkrótsze bajty / programista konkurencyjny. Po prostu lubię puzzle!
( Źródło )
źródło
Odpowiedzi:
Python 3, 423 bajty
Odczytuje dane wejściowe ze STDIN i zapisuje dane wyjściowe do STDOUT, używając tego samego formatu, co przykładowe dane wejściowe / wyjściowe.
Wyjaśnienie
Dla każdej linii tekstu zaszyfrowanego wykonujemy następującą procedurę:
Trzymamy mapę M wszystkich transformacji liter, które już ustaliliśmy (która początkowo jest pusta). Robimy to w taki sposób, aby wszystkie litery źródłowe były pisane małymi literami, a litery docelowe - dużymi.
Przetwarzamy słowa w tekście zaszyfrowanym w kolejności. Dla każdego słowa znajdujemy wszystkie słowa w słowniku, które mogą być dopasowane, w następujący sposób:
Załóżmy, że nasze słowo, w , jest
glpplppljjl
i że M zawiera regułęj -> P
. Najpierw przekształcamy w używając istniejących reguł w M , otrzymującglpplpplPPl
. Następnie przekształcamy w w następujący regex o smaku Pythona:Zasady transformacji są następujące:
x
, jest zastępowane przez . Definiuje nazwaną grupę przechwytywania, o nazwie , która pasuje do jednego znaku.(?P<
x
>.)
x
x
jest zastępowane przez . Jest to odniesienie do postaci wcześniej schwytanej przez wskazaną grupę .(?P=
x
)
x
Wykonujemy tę transformację poprzez odwrócenie w , a następnie zastosowanie dwóch następujących podstawień wyrażeń regularnych:
a następnie odwrócenie wyniku. Zauważ, że znaki wcześniej przekształcone przez M pojawiają się jako wielkie litery, a zatem pozostają niezmienione.
Dopasowujemy wynikowe wyrażenie regularne do każdego słowa w słowniku, przy czym słowa w słowniku pojawiają się jako wielkie litery. Na przykład powyższe wyrażenie regularne pasuje do słowa
MISSISSIPPI
. Jeśli znajdziemy mecz, możemy wyodrębnić nowe zasady transformacji od niego, i dodać je do M . Nowe reguły transformacji to po prostu znaki przechwycone przez każdą z grup przechwytywania. W powyższym wyrażeniu regularnymg
dopasowaniaM
grupowe,l
dopasowania grupoweI
ip
dopasowania grupoweS
dają nam regułyg -> M, l -> I, p -> S
. Musimy upewnić się, że wynikające reguły są spójne, to znaczy, że żadne dwie litery źródłowe nie są odwzorowane na tę samą literę docelową; w przeciwnym razie odrzucamy dopasowanie.Następnie przechodzimy do następnego słowa, korzystając z rozszerzonych reguł transformacji. Jeśli możemy dopasować wszystkie słowa zaszyfrowane za pomocą tego procesu, odszyfrowaliśmy tekst. Jeśli nie możemy dopasować słowa do któregokolwiek ze słów ze słownika, cofamy się i próbujemy dopasować poprzednie słowa do różnych słów ze słownika. Jeśli ten proces się nie powiedzie, nie ma rozwiązania i drukujemy rząd gwiazdek.
źródło
CJam,
6256 bajtówDość powolny i wymagający pamięci, ale działa w przypadku testowym z interpreterem Java.
Przykładowy przebieg
źródło