好像这个挑战可能在本质上是更多的Python风格 ... 不需要先验的Markov链或加密技术知识。
您是间谍,需要从英国安全服务M1S获得一些关键信息。M1S的代理很清楚,他们的Wi-Fi信号可以被拦截,利用了他们的Android / iOS安全漏洞等,因此他们所有人都使用Nokia 3310来传输使用T9自动完成功能键入的文本信息。
您以前曾破解过要交付给情报机构的电话,并在光荣的塑料键盘下安装了键盘记录程序,所以现在您收到的数字序列与他们键入的字母相对应,因此“ 鹰离开了巢穴提醒代理商 ”
84303245304270533808430637802537808430243687
可是等等!某些T9序列含糊不清(“ 6263”可能是“名称”,“鬃毛”或“双簧管”;模糊性越大,可疑性就越大!),那么您该怎么办?您知道,M1S唯一使用的入学考试是在15秒内总结Marcel Proust的杰作“回忆过去的事”,因此您要根据整个主厨中的频率分布来选择上一个单词之后的单词。普鲁斯特的魅力!
您可以破解代码并获取原始消息吗?
T9的原理
T9自动完成机制可以描述如下。如上图所示,它将字母字符映射为数字。
abc -> 2
def -> 3
ghi -> 4
jkl -> 5
mno -> 6
pqrs -> 7
tuv -> 8
wxyz -> 9
<space> -> 0
<other> -> <is deleted>
T9解密器接收到一个数字序列,并尝试猜测可以通过这些按键键入的单词。它可能使用标准的频率表,但我们要进一步走一步,并使用马尔可夫链预测下一个单词!
学习样本
该语料库是这严重剥夺普鲁斯特的“追忆似水年华”的版本(s/-/ /g
,s/['’]s //g
和s/[^a-zA-Z ]//g
-滚开迷惑的占有欲's
!)最初发表的对阿德莱德大学的网站(这项工作的文本是在公共领域在澳洲)。
必须将整个文本分析为一个字符串,一个长句子,一个单词长矢量(以您的语言更方便),去除换行符并在空格处拆分为单词。(我不提供单段文件,因为github工具可能会对此表示反对。)
如何将整个文本看成一个字符串/句子?R中的一个例子:
p_raw <- read.table("proust.txt", sep="\t") # Because there are no tabs
p_vec <- as.character(p_raw$V1) # Conversion to character vector
p_str <- paste(p_vec, collapse=" ") # One long string with spaces
p_spl <- strsplit(p_str, split=" ")[[1]] # Vector of 1360883 words
proust <- p_spl[p_spl!=""] # Remove empty entries — 1360797
任务
给定一个数字序列作为数字,返回一个可能的文本字符串,该字符串可以使用概率链使用相应的T9键键入,以根据被视为一个长句子的该训练文本来预测下一个单词X。
如果X是文本的第一个T9单词,并且有多个猜测,则随机选择一个,否则仅选择一个。
对于所有后续的T9单词X(i)之前已解密的单词w(i-1):
- 如果可以用一种独特的方式将T9单词X转换为普通单词x,请执行此操作。
- 如果X有多个可用的转换选项,例如x1,x2,...,请查找前面的猜词w。
- 如果w在Proust的原始作品中从未跟随任何映射到X的东西,请随机选择任何可能的x1,x2,...。
- 如果w X始终与原始x中的w x1相对应,并且没有可以映射到X中的并发xi,则选择x1。
- 如果宽x可以转换为w ^ X1,w ^ X2,...可以在语料库中发现,再算上所有可能喜的是后续W¯¯并映射到X在语料库和挑喜的概率XI /(X1 + x2 + ...)。
实施例2a。如果消息是76630489
,则where 489
可能是guy
or ivy
(它们在语料库中至少出现一次)7663
可以被解读为some
(一个非常可能的第一个单词)。如果some
从未489
在语料库中映射到任何内容,则以0.5的概率随机选择guy
或ivy
。
实施例2b。如果消息是766302277437
,那里2277437
可能是barrier
或carrier
,7663
可以被破译的some
。如果Proust总是使用some carrier
并且从不使用some barrier
,那么选择some carrier
。
实施例2c。假设您要解密序列536307663
。5363
被预测为lend
。7663
可以是任何这些:pond
,roof
和some
。您可以计算lend
示例语料库中后续单词的出现次数。假设您得到这样的信息(只是为了说明):
T9 Word following lend Occurrences
7663 some 7
7663 pond 2
7663 roof 1
因此,如果7663
在此之前lend
,则有分别代表20%和10%的7/(7+2+1)=70%
概率。您的算法应在70%的情况下,在20%的情况下等产生。7663
some
pond
roof
lend some
lend pond
您可以放心地假定代理仅使用az字母和空格(不带标点符号,所有格's
和数字)。
您可能还假设M1S的代理人永远不会使用“回忆过去的事”(这是一个多达29,237个单词的巨大词汇!)范围之外的单词。
T9功能在此挑战中得到了实现,因此您可以看一下。
如果您需要任何帮助,则可以很轻松地在此,该以及随后的挑战中驯服概率链,但是您甚至不需要了解这种链的原理:任务中已陈述了一切。
测试用例
--Inputs--
20784250276960369
20784250276960369
84303245304270533808430637802537808430243687
94280343084306289072908608430262780482737
94280343084306289072908608430262780482737
--Possible outputs--
c quick brown fox
a stick crown fox
the eagle gas left the nest blest vie agents
what did the navy pay to the coast guards
what did the navy raz un the coast guards
规则:
- 有标准漏洞。
- 您不知道原始消息,您所得到的只是一个数字序列和文件proust.txt,您只需要将该文件加载到内存/工作空间/任何内容中。不需要任何独立的东西。假设
proust.txt
始终可以访问。 - 如果根据语料库可能有多个解密选项,您的算法必须能够产生具有不同概率的不同输出(请参见示例2c)。
您需要保持谨慎,以最短的代码为准!
PS这种概率算法的明显好处是,对于歧义破译的字符串而言,获得真正的原始字符串的概率趋向于一个-稍等...
PPS 另请参见部分匹配预测。