Algorithm 写一个拼字算法

Algorithm 写一个拼字算法,algorithm,Algorithm,我正在研究一个类似填字游戏的问题,但我不知道如何设计算法 例如: * | +----+----+ | | A* B | | +--+--+ E* | | | P S +-+-+ | | | | P* K* A E* | | +-+-+ +-+-+

我正在研究一个类似填字游戏的问题,但我不知道如何设计算法

例如:

          *
          |
     +----+----+
     |         |
     A*        B
     |         |
  +--+--+      E*
  |     |      |
  P     S    +-+-+
  |     |    |   |
  P*    K*   A   E*
  |          |
+-+-+      +-+-+
|   |      |   |
E   L      D*  N*
|   |
A   E*
|
L*
  • 字典里有像“汽车”、“苹果”这样的词
  • “应用程序”一词出现在黑板上
  • 有像“l”“e”“c”“r”这样的字母用来造字
因此,该算法的任务是生成存储在词典中的正确单词

app->lapp->LEPP->lecapp->lappe->eappc->…->appl->apple(正确答案)


此算法的最佳解决方案是什么?

将词典存储为树,例如:

          *
          |
     +----+----+
     |         |
     A*        B
     |         |
  +--+--+      E*
  |     |      |
  P     S    +-+-+
  |     |    |   |
  P*    K*   A   E*
  |          |
+-+-+      +-+-+
|   |      |   |
E   L      D*  N*
|   |
A   E*
|
L*
感谢paxdiablo让我的树更具可读性

这棵树上有a、app、app、apple、ask、bead、bean、be和bee等词。标有星号的节点表示“如果我停在这里,这将是一个有效的单词”,例如“be”的“b”下面的“e”

当您找到一个您不知道的字母时,请使用通配符(即,选择所有子项并沿所有路径递归)

你说的是填字游戏,但你的“字母…用来造字”似乎表示拼字。这两种方法都适用。不是最快的,但速度非常快

感谢Andreas提醒我们这叫做trie


如果你想说“第二个字母是一个p”,你可以从根节点开始,然后取每个分支(假设它是一本合适的字典,那么它就是字母表中的每个字母),然后是“p”分支,然后从那里继续(隐晦,但结构背后的理论是相同的)

我有一个单词及其线索的数据库,可以根据使用的时间进行排序(这样我就不会在以后的运行中得到重复的填字游戏)

你应该做的第一件事是设计你的图案(黑色的不能放字母,白色的可以放)。在创建图案时尝试将单词放入网格非常耗时,而且容易出错。如果查看大多数纵横字谜,它们往往会遵循某些规则以使其更容易。例如,在其中一条对角线周围对称,以及不允许四个白格组成的正方形(以简化选择合适单词的任务)

一旦你有了这个模式,你就开始寻找要放在其中的词。这样,你就知道“app”是这个词的开头,并且能够将搜索限制在那些以“app”开头的词上,而不是每个有“app”的词上类似地,对于在任何位置都已知字母的单词,在已知位置找到字母的单词要比在单词的任何起始位置评估字母容易得多

我的最终是用shell脚本编写的(信不信由你),并使用Linux提供的字典作为单词搜索工具。如果你知道你有一个以“app”开头的5个字母的单词,那么它很容易使用:

grep '^app..$' words.txt
获取所有有效可能性的列表

当发现每个单词时,它被复制到一个包含单词和多个可能线索的clues.txt文件中。实际的格式是use{count,word,cluer}如果同一个单词可能存在于多行不同的线索中-这允许
grep
通过
sort
进行管道排列,以便较少使用的单词/线索浮到顶部(每当使用一个单词/线索时,其计数都会增加,从而减少下次使用的可能性)

一旦文件大小合适,程序将首先使用它来定位单词,只有在没有找到单词的情况下,它才会恢复到需要手动干预的单词文件(无线索)

它实际上非常擅长做这项工作。它的速度并不快,但我不需要每三秒生成一份——这是一份每周发送一次的社区通讯


既然你已经把问题改成了拼字游戏,那就更难了

你需要考虑你拥有的字母,黑板上的字母,还有你需要评估的地方更多,这使得暴力方法更加困难

作为初始切分,我要做的是选择随机选择的可能性(板上的起始位置和方向),然后使用与上述纵横字谜变体相同的算法来定位所有适合的单词。然后,如果你有字母来满足该单词,将其(连同分数)存储在列表中

记住,你需要注意不要干扰黑板上的其他单词

我将继续研究各种可能性,直到:

  • 您的列表足够大,可以从中进行选择
  • 你没时间了
  • 您已经检查了足够的可能性,以满足您的能力水平
最后一点很重要——如果你是初学者,你不想彻底地研究数百万种可能性


然后,从你的列表中选择最好的移动(如果是初学者,可能不是最好的-这取决于你希望计算机有多好)。

如果你试图创建一个单词索引,以便尝试“解决”(或创建)纵横字谜然后我想你应该从一本按长度索引的单词词典开始。然后你会创建另一本字典词典……第一个索引是按单词的总长度,第二个是按长度,然后是按字母位置,最后是按字母(例如,六个字母的单词,第二个字母是“I”)

建立此索引后,您可以根据对这些索引执行的集合操作来表示尝试设置或解决难题的每个步骤。(例如,以“w”开头并以“k”结尾的8个字母的单词将是以“w”开头的所有8个字母的单词与以“k”结尾的所有8个字母的单词的交点。)---毫不奇怪,其中包括“家庭作业”)。建立了我所描述的索引数据结构,当然,考虑到更多的效率
<?
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 + $scorez;
$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);

$a = 0;
$b = 0;
$c = 0;
$d = 0;
$e = 0;
$f = 0;
$g = 0;
$h = 0;
$i = 0;
$j = 0;
$k = 0;
$l = 0;
$m = 0;
$n = 0;
$o = 0;
$p = 0;
$q = 0;
$r = 0;
$s = 0;
$t = 0;
$u = 0;
$v = 0;
$w = 0;
$x = 0;
$y = 0;
$z = 0;
 }
?>