파이썬 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을 유지합니다 (처음 비어 있음). 소스 문자가 모두 소문자이고 대상 문자가 모두 대문자가되도록합니다.
암호문의 단어를 순서대로 처리합니다. 각 단어에 대해 다음과 같이 사전에서 일치하는 모든 단어를 찾습니다.
우리의 단어 w 가 glpplppljjl
있고 M 이 규칙을 포함 한다고 가정하자 j -> P
. 먼저 M 의 기존 규칙을 사용하여 w 를 변환 하여을 얻습니다 . 그런 다음 w 를 다음과 같은 파이썬 풍미 정규 표현식으로 변환합니다 .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 를 뒤집은 다음 다음 두 정규식 대체를 적용 하여이 변환을 수행합니다 .
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
합니다. 결과 규칙이 일치하는지 확인해야합니다. 즉, 두 개의 원본 문자가 동일한 대상 문자에 매핑되지 않아야합니다. 그렇지 않으면, 우리는 경기를 거부합니다.
그런 다음 확장 변환 규칙을 사용하여 다음 단어로 진행합니다. 이 프로세스를 사용하여 모든 암호문 단어를 일치시킬 수 있으면 텍스트를 해독 한 것입니다. 사전 단어와 일치하는 단어를 찾을 수 없으면 이전 단어를 다른 사전 단어와 역 추적하고 일치 시키려고합니다. 이 프로세스가 실패하면 해결책이 없으며 별표가 인쇄됩니다.