不可解なキッカー//


12

不可解なキッカー

テキストを暗号化する一般的だが安全ではない方法は、アルファベットの文字を入れ替えることです。言い換えると、アルファベットの各文字は、テキスト内で一貫して他の文字に置き換えられます。暗号化が可逆的であることを保証するために、2つの文字が同じ文字に置き換えられることはありません。あなたの仕事は、各行が異なる置換のセットを使用し、解読されたテキストのすべての単語が既知の単語の辞書からであると仮定して、テキストのいくつかのエンコードされた行を解読することです。

入力

入力は、アルファベット順の小文字の単語で構成されます。これらの単語は、復号化されたテキストに表示される単語の辞書を構成します。辞書に続いて、入力のいくつかの行があります。各行は上記のように暗号化されます。

辞書にあるのは1,000語以下です。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
> input <制約を各言語に適用可能なものに緩和してください。たとえば、多くの言語は嫌いであり、形式が6で始まることを理解していません。形式を完全に指定せず、入力は暗号化する単語のリストと行のリストであると言うことをお勧めします。
orlp

さて、そこに行きます!
Dhruv Ramani

1
これに実行時の制約はありますか?1つが動作するまで、おそらくすべての可能な置換の組み合わせを繰り返すことができます(これにはおそらく何年もかかります)
ネイサンメリル

@NathanMerrillそれをしてください、そしてそれが何年もかかるなら、ただ星形でそれを印刷してください。Vihan、重複していないので、質問を適切に読んでください。
Dhruv Ramani

単語を出力するだけでいいのでしょうか、それとも結合する必要がありますか?
ダウンゴート

回答:


3

Python 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に出力を書き込みます。

説明

暗号文の各行に対して、次の手順を実行します。

すでに確立したすべての文字変換(最初は空です)のマップMを保持します。ソース文字がすべて小文字で、宛先文字がすべて大文字になるようにします。

暗号文の単語を順番に処理します。各単語について、次のように、一致する可能性のある辞書内のすべての単語を検索します。

単語wglpplppljjlあり、Mにruleが含まれているとしますj -> P。最初にMの既存のルールを使用してwを変換し、を取得します。次に、wを次のpython風味の正規表現に変換します。glpplpplPPl

(?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を逆にして、次の2つの正規表現置換を適用することにより、この変換を実行します。

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つのソース文字が同じ宛先文字にマップされないことを確認する必要があります。そうでない場合、一致を拒否します。

次に、拡張変換ルールを使用して、次の単語に進みます。このプロセスを使用してすべての暗号文の単語を一致させることができれば、テキストを解読しました。単語を辞書の単語のいずれにも一致させることができない場合、バックトラックし、以前の単語を別の辞書の単語に一致させようとします。このプロセスが失敗した場合、解決策はなく、アスタリスクの行を出力します。


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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.