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(最初为空)。我们这样做的方式是,源字母全为小写,目标字母全为大写。
我们按顺序处理密文中的单词。对于每个单词,我们在字典中找到所有可能匹配的单词,如下所示:
假设我们的单词w是glpplppljjl
并且M包含规则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,然后应用以下两个正则表达式替换来执行此转换:
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
。我们必须确保产生的规则是一致的,也就是说,没有两个源字母映射到相同的目标字母。否则,我们拒绝比赛。
然后,我们使用增强的转换规则进入下一个单词。如果使用此过程可以匹配所有密文单词,则我们已经解密了文本。如果我们无法将单词与任何词典单词进行匹配,我们将回溯并尝试将先前的单词与不同词典单词进行匹配。如果此过程失败,则没有解决方案,我们将打印一行星号。