Python 3, 423 byte
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))
Đọc đầu vào từ STDIN và ghi đầu ra vào STDOUT, sử dụng cùng định dạng với đầu vào / đầu ra mẫu.
Giải trình
Đối với mỗi dòng của bản mã, chúng tôi thực hiện quy trình sau:
Chúng tôi giữ một bản đồ, M , trong tất cả các biến đổi chữ cái mà chúng tôi đã thiết lập (ban đầu trống). Chúng tôi làm điều đó theo cách mà các chữ cái nguồn đều là chữ thường và các chữ cái đích đều là chữ hoa.
Chúng tôi xử lý các từ trong bản mã theo thứ tự. Đối với mỗi từ, chúng tôi tìm thấy tất cả các từ trong từ điển có thể phù hợp, như sau:
Giả sử rằng từ của chúng ta, w , là glpplppljjlvà M chứa quy tắc j -> P. Đầu tiên chúng ta chuyển đổi w bằng cách sử dụng các quy tắc hiện có trong M , nhận glpplpplPPl. Sau đó chúng tôi chuyển đổi w thành regex có hương vị trăn sau đây:
(?P<g>.)(?P<l>.)(?P<p>.)(?P=p)(?P=l)(?P=p)(?P=p)(?P=l)PP(?P=l)
Các quy tắc của chuyển đổi như sau:
- Sự xuất hiện đầu tiên của mỗi chữ cái viết thường
x, được thay thế bằng . Điều này xác định một nhóm bắt giữ được đặt tên, được gọi , phù hợp với một cahracter duy nhất.(?P<x>.)x
- Mỗi lần xuất hiện tiếp theo, mỗi chữ cái viết thường
x, được thay thế bằng . Đây là một phản ứng ngược với nhân vật được nhóm có tên bắt trước .(?P=x)x
Chúng tôi thực hiện chuyển đổi này bằng cách đảo ngược w , sau đó áp dụng hai thay thế regex sau:
s/([a-z])(?!.*\1)/)>\1<P?(/
s/([a-z])(?=.*\1)/)\1=P?(/
và sau đó đảo ngược kết quả. Lưu ý rằng các ký tự được chuyển đổi trước đó bởi M xuất hiện dưới dạng chữ hoa và do đó không thay đổi.
Chúng tôi kết hợp regex kết quả với từng từ trong từ điển, trong đó các từ trong từ điển xuất hiện dưới dạng chữ hoa. Ví dụ, regex ở trên sẽ khớp với từ này MISSISSIPPI. Nếu chúng ta tìm thấy một trận đấu, chúng tôi trích xuất các quy tắc chuyển đổi mới từ nó, và thêm chúng vào M . Các quy tắc chuyển đổi mới chỉ đơn giản là các ký tự được bắt bởi mỗi nhóm bắt giữ. Trong regex ở trên, các gtrận đấu Mnhóm , ltrận đấu nhóm Ivà ptrận đấu nhóm S, cho chúng ta các quy tắc g -> M, l -> I, p -> S. Chúng ta phải đảm bảo rằng các quy tắc kết quả là nhất quán, nghĩa là không có hai chữ cái nguồn ánh xạ tới cùng một chữ cái đích; nếu không, chúng tôi từ chối trận đấu.
Sau đó chúng tôi tiến hành từ tiếp theo, sử dụng các quy tắc chuyển đổi tăng cường. Nếu chúng ta có thể kết hợp tất cả các từ mã hóa bằng quy trình này, chúng ta đã giải mã được văn bản. Nếu chúng tôi không thể ghép một từ với bất kỳ từ nào trong từ điển, chúng tôi sẽ quay lại và cố gắng khớp các từ trước đó với các từ trong từ điển khác nhau. Nếu quá trình này thất bại, không có giải pháp và chúng tôi in một hàng dấu hoa thị.