PHP 字谜解谜器
Posted
技术标签:
【中文标题】PHP 字谜解谜器【英文标题】:PHP anagram puzzle solver 【发布时间】:2015-10-31 14:48:08 【问题描述】:我正在尝试为我正在开发的 php 解谜程序寻找解决方案。
这是一个字谜求解器,需要用“给游泳者的消息”中的 16 个字母的 4 个字母字谜填充一个 4x4 网格。
水平行和垂直列需要完成短语的 4 个字母字谜。以下是预期的结果,但我的程序必须自行解决。
S M O G
W E R E
I T E M
M A S S
我创建它的尝试超时了。我正在尝试这样的事情:
foreach($word_array as $word)
$board = array();
$available = $default_array;
$row1 = $trie->run_word_check($word[0],$available);
if($row1)
echo "current row1 check: ". $row1."<br/>";
remove_from_available($row1,$available);
$board[] = $row1;
$col1 = $trie->run_word_check($row1[0],$available);
if($col1)
echo "current col1 check: ". $col1."<br/>";
remove_from_available($col1,$available);
$board[] = $col1;
$row2 = $trie->run_word_check($col1[0],$available);
if($row2)
echo "current row2 check: ". $row2."<br/>";
remove_from_available($row2,$available);
$board[] = $row2;
$col2 = $trie->run_word_check($row1[1].$row2[1],$available);
if($col2)
etc...
【问题讨论】:
不要仅仅定义问题,而是显示您目前拥有的代码,我们可以帮助它更好地工作 好吧,这就是我不太确定如何解决这个难题的问题。我创建了一个前缀树来快速找到可能的单词,但我似乎无法找到解决难题的方法。 你的$word_array
是从哪里得到的?
【参考方案1】:
你可以这样做:
预处理您的 4 字母单词列表,以便将它们作为键(值为 1 或其他值)以及它的每个前缀。因此,当您有一个用于“SWIM”的键时,您也将有一个用于“S”、“SW”和“SWI”的键。这将有助于在选择几个字符后快速检查是否仍有可能完成一个 4 字母单词。
预处理 16 个字母的输入字符串:将单个字母存储为键,其值等于该字符串中出现的次数。因此,对于“给游泳者的消息”,键“S”的值为 3。
保持4个水平词和4个垂直词。当然,这有一些冗余(因为垂直的可以从水平的推导出来),但这将有助于快速访问它们。这两个包含 4 个单词的数组,将从所有空字符串开始。
然后从第二个数组中取出一个字母(即可用字母及其计数)用于网格中的位置 0,0,并将其存储为第一个水平单词和 作为第一个垂直词。检查是否有以此开头的 4 个字母的单词。
如果有 4 个字母的单词的可能性,则使用递归将下一个字母放在网格中的 1,0 处。将该字母添加到第一个水平单词(所以现在它有 2 个字符)并将其放在第二个垂直单词中(那里只有 1 个字符)。再次检查。
重复递归,直到网格中的所有元素都已填充或找不到字母,当将其添加到适当的水平和垂直单词时,会产生无法进一步完成以匹配 4 个字母单词的内容.在后一种情况下,回溯并尝试其他角色。
以上是粗略的描述。代码如下:
$solution = anagram("Message to swimmer", get_words());
print_r ($solution);
function index_words($word_array)
$dict = [ '' => 1 ];
foreach ($word_array as $word)
for ($len = 1; $len <= 4; $len++)
$dict[substr($word, 0, $len)] = 1;
return $dict;
function letter_counts($available)
$letters = [];
foreach(str_split(strtoupper($available)) as $letter)
if (ctype_alpha($letter))
$letters[$letter] = isset($letters[$letter]) ? $letters[$letter]+1 : 1;
return $letters;
function anagram($available, $word_array) // Main algorithm
$dict = index_words($word_array); //keys = all 4 letter words, and all their prefixes
$letters = letter_counts($available); // key = letter, value = occurrence count
$hori = ['','','','']; // store the words that are formed horizontally per row
$vert = ['','','','']; // store the words that are formed horizontally per column
$recurse = function ($row, $col)
use (&$recurse, &$letters, &$dict, &$hori, &$vert, &$limit)
if ($row == 4) return true; // all done. backtrack out of recursion
$h = $hori[$row];
$v = $vert[$col];
foreach($letters as $letter => $count) // for each available character
if (!$count) continue; // not available any more
$word1 = $h . $letter;
$word2 = $v . $letter;
if (isset($dict[$word1]) && isset($dict[$word2]))
// It is still possible to form 4-letter words after placing this letter
$hori[$row] = $word1;
$vert[$col] = $word2;
$letters[$letter]--;
// use recursion to find characters for next slots in the grid
if ($recurse($row + ($col == 3 ? 1 : 0), ($col + 1) % 4)) return true;
// backtrack
$letters[$letter]++;
$hori[$row] = $h;
$vert[$col] = $v;
;
$recurse(0, 0); // start the recursive placement of letters in the grid
return $hori; // return the 4 words that were placed horizontally
function get_words() // returns a comprehensive list of 4 letter words
return [
'AAHS', 'AALS', 'ABAC', 'ABAS', 'ABBA', 'ABBE', 'ABBS', 'ABED', 'ABET', 'ABID', 'ABLE',
/* etc... long list of 4-letter words ... */
'ZOOM', 'ZOON', 'ZOOS', 'ZOOT', 'ZORI', 'ZOUK', 'ZULU', 'ZUPA', 'ZURF', 'ZYGA', 'ZYME',
'ZZZS'];
你可以看到它在eval.in上运行。
用here发布的4个字母单词,不到0.2秒就找到了下面的解:
M E G S
O W R E
M E A T
I S M S
...结果当然取决于单词列表。我必须查一下 OWRE 是什么意思 ;-)
【讨论】:
天哪!你为此付出的努力得到了可悲的回报!今天回答这么老的问题你有多无聊!?以上是关于PHP 字谜解谜器的主要内容,如果未能解决你的问题,请参考以下文章
您将如何处理 PHP + MySQL 字谜求解器? [关闭]