我有一段文字被两个字符列填满。我的任务目的是解读它:
|de| | f|Cl|nf|ed|au| i|ti| |ma|ha|or|nn|ou| S|on|nd|on|
|ry| |is|th|is| b|eo|as| | |f |wh| o|ic| t|, | |he|h |
|ab| |la|pr|od|ge|ob| m|an| |s |is|el|ti|ng|il|d |ua|c |
|he| |ea|of|ho| m| t|et|ha| | t|od|ds|e |ki| c|t |ng|br|
|wo|m,|to|yo|hi|ve|u | t|ob| |pr|d |s |us| s|ul|le|ol|e |
| t|ca| t|wi| M|d |th|"A|ma|l |he| p|at|ap|it|he|ti|le|er|
|ry|d |un|Th|" |io|eo|n,|is| |bl|f |pu|Co|ic| o|he|at|mm|
|hi| | |in| | | t| | | | |ye| |ar| |s | | |. |
我目前找到正确的列顺序的方法是尝试根据单词出现次数标准递归查找每列的最佳位置。
我想到的算法核心的伪代码是:
function unscramble(scrambledMatrix,indexOfColumnIveJustMoved)
for each column on scrambledMatrix as currentIndex=>currentColumn
if (currentIndex!=indexOfColumnIveJustMoved)
maxRepeatedWords=0;maxIndex=0;
for (i=0;i<numberOfColumnsOfScrambledMatrix;i++)
repWordsCount=countRepWords(moveFromToOn(currentIndex,i,scrambledMatrix))
if (maxRepeatedWords<repWordsCount)
maxRepeatedWords=repWordsCount;
maxIndex=i;
endif
endfor
if (maxIndex!=currentIndex)
return unscramble(moveFromToOn(currentIndex,maxIndex,scrambledMatrix),maxIndex); //recursive call
endif
endif
endfor
return(scrambledMatrix); //returns the unscrambled matrix;
endfunction
在迭代每个列后没有移动列时,算法会停止。我猜它应该适用于任何语言(尽管我只对英语解决方案感兴趣),只要写作基于字母形成的单词并且样本足够大。
对任何其他方法或改进有任何建议吗?我想知道这个问题的最佳解决方案(可能是基于字典的一个寻找常见字的出现?如何重建算法以避免递归,它会更快吗?)。
答案 0 :(得分:1)
还有一些想法:
一种方法,尽管这种方法通常是最耗时的方法之一 - 使用遗传算法。
让我们说列的当前默认排列是
|de| | f|Cl|nf|ed|au| i|ti| |ma|ha|or|nn|ou| S|on|nd|on|
[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18] <--- define this to be a chromosome
您可以创建一个100,1000 w / e染色体数量的群体,这些染色体从随机分配开始(请记住'随机'分配不能有重复的数字且必须有效)
然后在每个任务上运行一个健身功能,或者如果你想以这种方式分解它,可以运行多个健身功能。从一个超级健身功能开始,为每个任务分配一个健身值。
只取最前面50%的染色体并将它们移到下一代,根据您选择的交叉函数和突变概率创建“儿童”染色体 - 对于这类问题,我建议使用非常轻的染色体交叉函数(或没有......)和一个不错的突变率。如果你能找到对单词/适应度函数没有贡献的列,那么可以翻转它们。
继续这么做几代人,看看最受好评的作业如何看起来像每一代,你会期望在某个时刻有效到高峰,这将是你正确的作业。
这种方法只能比具有健身功能的蛮力稍微好一些,但它也可能会相当不错。
最后一个想法:尝试从'第一列,第二列'中抽象出来并将列分配成形成单词的块,因为只是因为[1,4,6 ....]结果形成了“the” “他”,“她”等,并不意味着它一开始就属于它。
我有一种不同的方法,我觉得更好,我认为动态算法更适合这一点。
编辑:另一种方法
再次基于字典方法,但你会专注于在休息之前选择前几列,如果它分崩离析并且你没有在任何特定行中得到单词,这意味着你之前的选择是错误的,你将需要回溯。
选择第1行......很有可能这里没有太多的单词,但是你会将自己缩小到你的字典的一个子集 - 这个子集的第一列中有以字符开头的单词。
现在您有一行有效,请选择右侧的相邻行。如果它形成完整的单词或仍然有可能的有效单词(假设没有空格,表示单词的结尾)。 重复。
如果您之前没有选择相邻的行,请向左回溯一行,不要再选择相同的行。
这里的缺点是你的词典需要包含你句子中的所有单词,以及单词的所有变体。您可能需要提出类似于健身功能的启发式功能,该功能说“90%的单词匹配,所以这仍然是一种有效的尝试......”或类似的东西。