写一个算法填字游戏
我工作的一个填字状的问题,但我不知道怎么设计的算法。
有喜欢的字典'车','苹果'字。
单词“应用程序”被赋予在黑板上。
有喜欢“L”“E”“C”“R”....制作单词的字母。
因此,该算法的任务是使它们存储在字典中正确的单词。
应用程序 - & LAPP
- & lecapp
- &申请 - &苹果(正确***)
这究竟是什么算法的最佳解决方案?
--------------解决方案-------------
您可能会感兴趣的由阿佩尔和雅各布森(1988)谷歌搜索的研究论文“世界上最快的拼字游戏节目”。 该算法的伪代码列出,所以它需要多一点工作,塑造了成可用的形式,并把它粘在一起; 然而,该方案的作者大纲的伟大工程。
你的字典存储为一棵树,例如:
+----+----+
+-+-+ +-+-+
感谢paxdiablo让我的树更具可读性。
这棵树有吸引力的话,苹果,问,珠,豆,是,和蜜蜂。 马克节点说:“如果我停在这里,这将是一个有效的字”,如下面的'B'的'E'为'是'。
当你发现了一封信,你不知道,使用通配符(即接所有的儿童和递归了所有的路径)。
你说的填字游戏,但你的“信......制作的话”似乎表明拼字游戏。 这将工作要么。 不是最快的,但足够快。
感谢安德烈亚斯提醒我们,这就是所谓的线索。
如果你想说“第二个字母是P”,你会从根节点开始,并抓住每一个分支(这将是字母表中的每一个字母,假设这是一个正确的字典),然后在“P”分支,然后去从那里。
其实我已经写了一个字谜程序之前(神秘但施工背后的理论是相同的)。
我有话和他们的线索,可以通过使用(所以我不会特意去在随后的运行中重复的填字游戏)时间进行排序的数据库。
你应该做的第一件事就是设计你的模式(黑,你不能把信件和白人在那里你可以)。 试图将字成一个网格,而动态创建的模式是非常耗时且容易出错。 如果你看看大多数的填字游戏,他们往往会遵循一定的规则,使其更容易。 之类的东西是对称围绕对角线之一和不允许四白细胞(缓和选择合适的词的任务)的平方。
一旦你的模式, 然后你开始找的话它的地方。 这样一来,你就知道“应用程序”是一个词的开头,并能限制你的搜索到那些以“应用程序”,而不是在其“应用程序”的每一个字。 同样的,你有权在任何位置称为字母的单词。 这是一个更容易找到与字母的单词,在已知的位置,而不是在一个字内的任何起始位置评估这些信件。
煤矿最终被写在shell脚本(信不信由你),并使用来自Linux作为一个单词搜索工具字典。 如果你知道你有一个5个字母的单词开始的“应用程序”,它很容易使用:
grep '^app..$' words.txt
要得到所有有效的可能性列表。
而且,每个字被发现,它被复制到包含这两个词和多个可能的线索clues.txt文件。 实际格式是使用{计数,字,线索}其中相同的字可存在于多行与不同的线索-这允许的管道grep通过sort ,使得较少使用的词语/线索浮到顶部(每当字/线索使用,它的计数递增,使得它不太可能被使用的下一个时间)。
一旦该文件是一个体面的大小,该程序将使用它首先找到的话,并且只有一人没有发现它会恢复的话文件(没有线索),其中将需要手动干预。
它实际上结束了,在做的工作相当不错。 这不是令人眼花缭乱的快,但我并不需要生成一个每三秒钟 - 这是一个社区的通讯每周发送一次。
现在,你已经将问题变成一个拼字变体,这其实更难。
你需要考虑到你的信件,在黑板上的字母和事实,即有,你必须评估多了很多地方。 这使蛮力方法更难。
我会做什么作为初始切口是选择随机选择的可能性(从电路板上的位置和方向),然后用同样的算法作为字谜变种上面找到能适合有所有单词。 然后,如果你有信来满足这个词,将其存储(连同其分)在列表中。
请记住,你需要注意与董事会换句话说干扰。
我会继续研究的可能性,直到之一:
你的名单足够大选择。
您运行的时间。
您研究了足够的准备,以满足你的能力水平。
这最后一个重要的 - 如果你正在玩一个初学者,你不希望详尽地检查数百万的可能性。
然后,选择从列表中的最佳移动(或也许不是最好的,如果打在入门级的水平 - 这一切都取决于你想如何好电脑来定)。
史蒂芬A.戈登写一篇关于如何寻找可能的拼字游戏一个有趣的文章(TM我猜的)移动(见戈登对GADDAG纸)。 虽然有搜索动作和获奖的拼字游戏有很大差距 - 作为纸张提到 - 这是不相关的原题。
如果你会发现它最有用的只是直来直去阅读一些代码,有一个很好的开源播放器,Quackle。
大多数的拼字游戏篇谈搜索整个板发挥最好的词。 但是,要解决你的问题,如前所述,有一个很简单的算法。
首先,你知道你想要的字包含'应用',你知道,你可以使最大的字是七个字母长(3个字母已经在船上,和4的盘)。 所以,用一个sql语句,如搜索数据库:
从字典中选择一个单词,其中单词LIKE'%应用%'和len(字)&= 7
接下来,把所有七个字母到一个数组{1,E,C,R,A,P,P}
从数据库中读取各一个字的时间。 然后看字典单词的每一个字符,看看它是否存在于数组中开始。 如果字典单词的第一个字母数组中被发现,然后删除该元素数组中,并移动到下一个字典信。
如果未在数组中找到的任何字典中的单词字母,那么这个词不符合,那么,移动到下一个单词。
如果你已经看过在字典中的所有字母,所有都在数组中被找到,那么这个词的资格,所以你把它写到列表中。
请注意,你把你的砖到一个数组的原因是,一旦你从字典单词一个字母匹配您的阵列中一瓦,你需要进一步考虑删除这封信中,删去了数组中的元素。
因此,例如,词典数据库返回词'上诉'。 前四个字母中找到你的阵列,并且这些元素被删除,只留下{升,C,R}左阵列中。 当您要查找的第五个字母“A”,你不会找到它,所以这个词被取消资格。
这个词“苹果”将有资格,留下{C,R}留在你的阵列。
这是很容易在任何语言代码这一点。 然而,这是不是这样做的最快方法。 我正在寻找更快的方法喽!
如果你想创建这样的话,你可以尝试“解决”(或创建)指数的填字游戏,然后我猜你会开始与长度索引词的字典。 然后,你想创建字典词典的另一个字典......第一个指标是总字长,而第二个是长度,然后用字母位置,最后由字母(六个字母的单词用“的第二封信我“ 例如)。
你已经建立了这个指标后,您就可以表达在试图设置或解决一个难题在对这些设置进行操作方面的每一步。
(例如以“W”和“K”结尾的8个字母单词是所有8个字母组成的单词以“W”和所有与“K”结尾---这勿庸置疑将包括“功课路口“)。 具有内置予描述,当然,所述索引数据结构,允许更高效搜索可能的匹配,然后将有可能通过执行只是全局单词列表的线性扫描或长度分隔的列表的偶数的线性扫描)。
一旦你有了这个基本的数据结构,那么该程序的其余部分将,想必,是一个树的生成和遍历(当然,回溯)。 创建一个程序,生成各种可能性(使用上述数据结构)和一个每当“卡”有它回溯,直到它找到了新的可能性。
由于暗示的paxdiablo,你必须包括为发电机有创建完成了一个合理的机会“改为”大池“的解决方案。” 谁是经历了填字游戏的人意识到,他们让二传手采取相当多的自由(如频繁使用指南针点,过时的条款和诗意的合同),以获得自己的光彩的驼峰,因为它是。
我没有亲自写了一个字谜发生器。 我已经写它采用了类似的密文解算器,但更简单的索引结构。
(要找到每一个字这zyzxw可以在一个密你“抽象”成一个模式:abacd你的字典有它的抽象索引的每一个字,你可以很容易地发现,“每一个”匹配“zyzxw”)。 在这种情况下,通过列表的线性搜索开始在每个抽象,甚至当你的关联是找出“UVZ”与“zyzxw”可能确实,是“”......为例)相当快。 我也写一个简单的“Jotto”游戏,这不利于从索引中都---线性扫描通过几千5或6个字母的单词,在使用的每个步消取远小于一秒在我的老6在现代PC计算的预历史兆赫XT)。
外观为博士论文论文布赖恩?谢泼德(Maven的作者)被称为“拼字游戏的走向完美的发挥”。 这是知识性和一个非常有趣的。 但也很长。
如果我理解正确的问题(你启动W??提示字母,单词的子字符串,并尝试重新排列字母得到一个正确的字)这里是另一种解决方案:
您可以通过向后展开。 你已经在字典中的单词和需要显示的字(子串)和信件从单词列表中的一部分,这样的人可以安排他们。 考虑到这一切,你开始从字典中的字,创造了1编辑距离字的图形了。
开始与苹果和保持取出一封信。 这里是一个小图(对此我没有画所有边缘,以减少混乱):
苹果 - & APPE
- &猿 - & ...
&NBSP \&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP&NBSP \
&NBSP&NBSP \ _-&申请 - &程序 - & ...
当你删除的信,你把它放在一个提示列表。
提示:L,P
提示:L,E
当玩家使用字母从列表中形成的原词,你接受这是节点而导致先前的父母唯一正确的条目。 你只要遍历图形往回走,找到原词。
如果单词应用程序,并 提示:L,P
如果用户给你L:申请你移动到应用程序的上一个节点,也就是申请。
如果用户给你E:APPE你移动到应用程序的上一个节点是APPE在这种情况下。
该用户输入,你不允许通过保持在当前节点的任何其他字母。
你正在寻找的是找到“通用”字母,看看在的话也可以用其他字母做的能力,为您字谜解算器。 我有一个字谜解算我写了这是否确切的事情。 一个重要的事情,我发现做这个,也为求解器的速度是预先确定有多少文字和每个单词在你的词汇表中的分数。
比如你表必须像这样
word | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z | score
-------------------------------------------------------------------------------------------------------------
test | 0 | 0 | 0 | 0 | 1 | 0 | 0 | h | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 4
正如你可以看到有单词,字母以及有多少封信它们含有与该单词的***独列。 我创造了这个时间提前了单独的脚本,仅仅跑了每个字,填补其在我,直到它被完成。
这是我写的计算很多信是如何在每一个字,以及得分和更新的每一条记录的脚本。 你必须开始,仅仅有句话在它之前,你可以运行此脚本的表。 当你运行它,那么你就做,不必再次运行它,除非你增加新单词。
include('/includes/connect.php');
$sql = &SELECT * FROM SOWPODS WHERE word LIKE 'z%' ORDER BY word ASC&;
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
$string = $row['word'];
$rowwordid = $row['ID'];
echo $thisword = strtoupper($row['word']);
echo & - &;
for ($ii = 0; $ii & strlen($string); ++$ii) {
$thisletter = strtolower($string{$ii});
if ($thisletter == 'a') {
$a = $a+1;
} elseif ($thisletter == 'b') {
$b = $b+1;
} elseif ($thisletter == 'c') {
$c = $c+1;
} elseif ($thisletter == 'd') {
$d = $d+1;
} elseif ($thisletter == 'e') {
$e = $e+1;
} elseif ($thisletter == 'f') {
$f = $f+1;
} elseif ($thisletter == 'g') {
$g = $g+1;
} elseif ($thisletter == 'h') {
$h = $h+1;
} elseif ($thisletter == 'i') {
$i = $i+1;
} elseif ($thisletter == 'j') {
$j = $j+1;
} elseif ($thisletter == 'k') {
$k = $k+1;
} elseif ($thisletter == 'l') {
$l = $l+1;
} elseif ($thisletter == 'm') {
$m = $m+1;
} elseif ($thisletter == 'n') {
$n = $n+1;
} elseif ($thisletter == 'o') {
$o = $o+1;
} elseif ($thisletter == 'p') {
$p = $p+1;
} elseif ($thisletter == 'q') {
$q = $q+1;
} elseif ($thisletter == 'r') {
$r = $r+1;
} elseif ($thisletter == 's') {
$s = $s+1;
} elseif ($thisletter == 't') {
$t = $t+1;
} elseif ($thisletter == 'u') {
$u = $u+1;
} elseif ($thisletter == 'v') {
$v = $v+1;
} elseif ($thisletter == 'w') {
$w = $w+1;
} elseif ($thisletter == 'x') {
$x = $x+1;
} elseif ($thisletter == 'y') {
$y = $y+1;
} elseif ($thisletter == 'z') {
$z = $z+1;
$scorea = $a*1;
$scoreb = $b*4;
$scorec = $c*4;
$scored = $d*2;
$scoree = $e*1;
$scoref = $f*4;
$scoreg = $g*3;
$scoreh = $h*3;
$scorei = $i*1;
$scorej = $j*10;
$scorek = $k*5;
$scorel = $l*2;
$scorem = $m*4;
$scoren = $n*2;
$scoreo = $o*1;
$scorep = $p*4;
$scoreq = $q*10;
$scorer = $r*1;
$scores = $s*1;
$scoret = $t*1;
$scoreu = $u*2;
$scorev = $v*5;
$scorew = $w*4;
$scorex = $x*8;
$scorey = $y*3;
$scorez = $z*10;
$totalscore = $scorea + $scoreb + $scorec + $scored + $scoree + $scoref + $scoreg + $scoreh + $scorei + $scorej + $scorek + $scorel + $scorem + $scoren + $scoreo + $scorep + $scoreq + $scorer + $scores + $scoret + $scoreu + $scorev + $scorew + $scorex + $scorey + $
$SQL_update_count = &UPDATE TWL06 SET a = '$a', b = '$b', c = '$c', d = '$d', e = '$e', f = '$f', g = '$g', h = '$h', i = '$i', j = '$j', k = '$k', l = '$l', m = '$m', n= '$n', o = '$o', p = '$p', q = '$q', r = '$r', s = '$s', t = '$t', u = '$u', v = '$v', w = '$w', x = '$x', y = '$y', z = '$z', score = '$totalscore' WHERE ID = '$rowwordid'&;
echo &&br&&;
$result_update_count = mysql_query($SQL_update_count);
一旦做到这一点那么所有你所要做的就是让这对在该列的字母,并与你给它的字母与它匹配的脚本。 你将不得不先爆炸的字母,并找出多少每个字母你的。 然后运行,发现这些款项字母或更少的SQL语句。
Copyright (C) , All Rights Reserved.
版权所有 京ICP备号
processed in 0.494 (s). 10 q(s)