C++ 什么样的Ruzzle板包含最独特的单词?
对于智能手机,有一个叫做的游戏。C++ 什么样的Ruzzle板包含最独特的单词?,c++,c,performance,algorithm,puzzle,C++,C,Performance,Algorithm,Puzzle,对于智能手机,有一个叫做的游戏。 这是一个找词游戏 快速解释: 游戏板由4x4个字母组成。 您可以从任意单元格开始,通过向上、向下、向左、向右或对角拖动来拼写单词。 电路板没有包装,您不能重复使用已选择的字母 平均来说,我和我的朋友会找到大约40个单词,在游戏结束时,游戏会告诉你可能会得到多少个单词。这个数字通常在250-350之间。 我们想知道什么样的电路板会产生最多可能的字数 我该如何找到最佳线路板? 我用C编写了一个程序,它包含16个字符,并输出所有适当的单词。 测试超过80000个单词
这是一个找词游戏 快速解释:
游戏板由4x4个字母组成。
您可以从任意单元格开始,通过向上、向下、向左、向右或对角拖动来拼写单词。
电路板没有包装,您不能重复使用已选择的字母 平均来说,我和我的朋友会找到大约40个单词,在游戏结束时,游戏会告诉你可能会得到多少个单词。这个数字通常在250-350之间。
我们想知道什么样的电路板会产生最多可能的字数 我该如何找到最佳线路板?
我用C编写了一个程序,它包含16个字符,并输出所有适当的单词。
测试超过80000个单词,处理大约需要一秒钟 问题:
游戏板排列的数量为26^16。
这是43608742998874059776(43个六位数) 我需要一些启发。
我是否应该跳过所有包含z、q、x、等的电路板,因为它们的字数预计不会太多?我不想在不确定的情况下排除一封信。
每个电路板也有4个副本,因为旋转电路板仍然会得到相同的结果。
但即使有这些限制,我认为我的生命中也没有足够的时间找到答案 也许董事会的产生不是答案。
有没有更快捷的方法从单词列表中找到答案?有趣的问题。我看到(至少但主要是)两种方法
- 根据80k字典
,您可以发现,对于26个字母的L集合中的每个l1字母,字母l2在l1之前或之后的概率。这是一个D
概率数组,它非常小,因此您甚至可以扩展到lxl
,即考虑l1和l2,l3要适应的概率是多少。如果算法想要估计准确的概率,这就有点复杂了,因为概率和取决于3个字母的相对位置,例如在“三角形”配置中(例如位置(3,3)、(3,4)和(3,5)),结果可能比字母对齐时要少[只是一个假设]。为什么不升级到lxlxl
,这将需要一些优化lxlxlxl
- 然后,您在电路板上随机分配几个高外观字母(比如4~6个)(在8个可能的方向中的至少5个方向上,每个字母周围至少有1个空白单元格),然后使用
probas数组来完成-基于现有字母的含义,下一个单元格填充一个字母,该字母的概率在给定的配置下是高的[同样,字母按概率降序排序,如果两个字母紧密相连,则使用随机性]L x L[xL]
ER
和to
之间找到最佳的2个字母
...ER??TO...
使用lxl
,类似循环(l1和l2是我们缺少的两个字母)。找到绝对更好的字母-但是bestchoice和bestproba可以改为数组,并保留10个最佳选择。
注:没有必要将概率保持在[0,1]的范围内。在这种情况下,我们可以将概率相加(虽然没有给出概率,但数字很重要。数学概率可以是p=(p(l0,l1)+p(l2,l3))/2,l0和l3是我们lxl
示例中的R和t)
该算法可以考虑更多的因素,并需要考虑垂直和对角线。使用lxlxl
,需要考虑更多方向上的字母,如ER?
,R???
,
请注意,其中很多可能是预先计算的,而lxl
数组当然是其中之一。tldr
S E R O
P I T S
L A N E
S E R G
或者它的任何反映
这个电路板包含1212个单词(事实证明,可以排除“z”、“q”和“x”)
首先,你用错了字典。在没有得到与Ruzzle的词数精确匹配的结果后,我调查了一下,Ruzzle似乎使用了一个名为TWL06的字典,它有大约180000个单词。不要问我它代表什么,但它在txt中是免费提供的
我还编写了代码,在16个字符的黑板上查找所有可能的单词,如下所示。它将字典构建成一个树状结构,然后在有单词需要查找时,几乎只是递归地循环。它按长度顺序打印它们。唯一性由STL集合结构维护
#include <cstdlib>
#include <ctime>
#include <map>
#include <string>
#include <set>
#include <algorithm>
#include <fstream>
#include <iostream>
using namespace std;
struct TreeDict {
bool existing;
map<char, TreeDict> sub;
TreeDict() {
existing = false;
}
TreeDict& operator=(TreeDict &a) {
existing = a.existing;
sub = a.sub;
return *this;
}
void insert(string s) {
if(s.size() == 0) {
existing = true;
return;
}
sub[s[0]].insert(s.substr(1));
}
bool exists(string s = "") {
if(s.size() == 0)
return existing;
if(sub.find(s[0]) == sub.end())
return false;
return sub[s[0]].exists(s.substr(1));
}
TreeDict* operator[](char alpha) {
if(sub.find(alpha) == sub.end())
return NULL;
return &sub[alpha];
}
};
TreeDict DICTIONARY;
set<string> boggle_h(const string board, string word, int index, int mask, TreeDict *dict) {
if(index < 0 || index >= 16 || (mask & (1 << index)))
return set<string>();
word += board[index];
mask |= 1 << index;
dict = (*dict)[board[index]];
if(dict == NULL)
return set<string>();
set<string> rt;
if((*dict).exists())
rt.insert(word);
if((*dict).sub.empty())
return rt;
if(index % 4 != 0) {
set<string> a = boggle_h(board, word, index - 4 - 1, mask, dict);
set<string> b = boggle_h(board, word, index - 1, mask, dict);
set<string> c = boggle_h(board, word, index + 4 - 1, mask, dict);
rt.insert(a.begin(), a.end());
rt.insert(b.begin(), b.end());
rt.insert(c.begin(), c.end());
}
if(index % 4 != 3) {
set<string> a = boggle_h(board, word, index - 4 + 1, mask, dict);
set<string> b = boggle_h(board, word, index + 1, mask, dict);
set<string> c = boggle_h(board, word, index + 4 + 1, mask, dict);
rt.insert(a.begin(), a.end());
rt.insert(b.begin(), b.end());
rt.insert(c.begin(), c.end());
}
set<string> a = boggle_h(board, word, index + 4, mask, dict);
set<string> b = boggle_h(board, word, index - 4, mask, dict);
rt.insert(a.begin(), a.end());
rt.insert(b.begin(), b.end());
return rt;
}
set<string> boggle(string board) {
set<string> words;
for(int i = 0; i < 16; i++) {
set<string> a = boggle_h(board, "", i, 0, &DICTIONARY);
words.insert(a.begin(), a.end());
}
return words;
}
void buildDict(string file, TreeDict &dict = DICTIONARY) {
ifstream fstr(file.c_str());
string s;
if(fstr.is_open()) {
while(fstr.good()) {
fstr >> s;
dict.insert(s);
}
fstr.close();
}
}
struct lencmp {
bool operator()(const string &a, const string &b) {
if(a.size() != b.size())
return a.size() > b.size();
return a < b;
}
};
int main() {
srand(time(NULL));
buildDict("/Users/XXX/Desktop/TWL06.txt");
set<string> a = boggle("SEROPITSLANESERG");
set<string, lencmp> words;
words.insert(a.begin(), a.end());
set<string>::iterator it;
for(it = words.begin(); it != words.end(); it++)
cout << *it << endl;
cout << words.size() << " words." << endl;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
结构树指令{
布尔现有;
地图分册;
TreeDict(){
存在=错误;
}
TreeDict&operator=(TreeDict&a){
现有=a.现有;
sub=a.sub;
归还*这个;
}
空白插入(字符串s){
如果(s.size()==0){
存在=真实;
#include <cstdlib>
#include <ctime>
#include <map>
#include <string>
#include <set>
#include <algorithm>
#include <fstream>
#include <iostream>
using namespace std;
struct TreeDict {
bool existing;
map<char, TreeDict> sub;
TreeDict() {
existing = false;
}
TreeDict& operator=(TreeDict &a) {
existing = a.existing;
sub = a.sub;
return *this;
}
void insert(string s) {
if(s.size() == 0) {
existing = true;
return;
}
sub[s[0]].insert(s.substr(1));
}
bool exists(string s = "") {
if(s.size() == 0)
return existing;
if(sub.find(s[0]) == sub.end())
return false;
return sub[s[0]].exists(s.substr(1));
}
TreeDict* operator[](char alpha) {
if(sub.find(alpha) == sub.end())
return NULL;
return &sub[alpha];
}
};
TreeDict DICTIONARY;
set<string> boggle_h(const string board, string word, int index, int mask, TreeDict *dict) {
if(index < 0 || index >= 16 || (mask & (1 << index)))
return set<string>();
word += board[index];
mask |= 1 << index;
dict = (*dict)[board[index]];
if(dict == NULL)
return set<string>();
set<string> rt;
if((*dict).exists())
rt.insert(word);
if((*dict).sub.empty())
return rt;
if(index % 4 != 0) {
set<string> a = boggle_h(board, word, index - 4 - 1, mask, dict);
set<string> b = boggle_h(board, word, index - 1, mask, dict);
set<string> c = boggle_h(board, word, index + 4 - 1, mask, dict);
rt.insert(a.begin(), a.end());
rt.insert(b.begin(), b.end());
rt.insert(c.begin(), c.end());
}
if(index % 4 != 3) {
set<string> a = boggle_h(board, word, index - 4 + 1, mask, dict);
set<string> b = boggle_h(board, word, index + 1, mask, dict);
set<string> c = boggle_h(board, word, index + 4 + 1, mask, dict);
rt.insert(a.begin(), a.end());
rt.insert(b.begin(), b.end());
rt.insert(c.begin(), c.end());
}
set<string> a = boggle_h(board, word, index + 4, mask, dict);
set<string> b = boggle_h(board, word, index - 4, mask, dict);
rt.insert(a.begin(), a.end());
rt.insert(b.begin(), b.end());
return rt;
}
set<string> boggle(string board) {
set<string> words;
for(int i = 0; i < 16; i++) {
set<string> a = boggle_h(board, "", i, 0, &DICTIONARY);
words.insert(a.begin(), a.end());
}
return words;
}
void buildDict(string file, TreeDict &dict = DICTIONARY) {
ifstream fstr(file.c_str());
string s;
if(fstr.is_open()) {
while(fstr.good()) {
fstr >> s;
dict.insert(s);
}
fstr.close();
}
}
struct lencmp {
bool operator()(const string &a, const string &b) {
if(a.size() != b.size())
return a.size() > b.size();
return a < b;
}
};
int main() {
srand(time(NULL));
buildDict("/Users/XXX/Desktop/TWL06.txt");
set<string> a = boggle("SEROPITSLANESERG");
set<string, lencmp> words;
words.insert(a.begin(), a.end());
set<string>::iterator it;
for(it = words.begin(); it != words.end(); it++)
cout << *it << endl;
cout << words.size() << " words." << endl;
}
string randomBoard() {
string board = "";
for(int i = 0; i < 16; i++)
board += (char)('A' + rand() % 26);
return board;
}
char distLetter() {
int x = rand() % 15833;
if(x < 1209) return 'A';
if(x < 1510) return 'B';
if(x < 2151) return 'C';
if(x < 2699) return 'D';
if(x < 4526) return 'E';
if(x < 4726) return 'F';
if(x < 5161) return 'G';
if(x < 5528) return 'H';
if(x < 6931) return 'I';
if(x < 6957) return 'J';
if(x < 7101) return 'K';
if(x < 7947) return 'L';
if(x < 8395) return 'M';
if(x < 9462) return 'N';
if(x < 10496) return 'O';
if(x < 10962) return 'P';
if(x < 10987) return 'Q';
if(x < 12111) return 'R';
if(x < 13613) return 'S';
if(x < 14653) return 'T';
if(x < 15174) return 'U';
if(x < 15328) return 'V';
if(x < 15452) return 'W';
if(x < 15499) return 'X';
if(x < 15757) return 'Y';
if(x < 15833) return 'Z';
}
string distBoard() {
string board = "";
for(int i = 0; i < 16; i++)
board += distLetter();
return board;
}
string changeLetter(string x) {
int y = rand() % 16;
x[y] = distLetter();
return x;
}
string swapLetter(string x) {
int y = rand() % 16;
int z = rand() % 16;
char w = x[y];
x[y] = x[z];
x[z] = w;
return x;
}
string change(string x) {
if(rand() % 2)
return changeLetter(x);
return swapLetter(x);
}
int main() {
srand(time(NULL));
buildDict("/Users/XXX/Desktop/TWL06.txt");
string board = "SEROPITSLANESERG";
int locmax = boggle(board).size();
for(int j = 0; j < 5000; j++) {
int changes = 1;
string board2 = board;
for(int k = 0; k < changes; k++)
board2 = change(board);
int loc = boggle(board2).size();
if(loc >= locmax && board != board2) {
j = 0;
board = board2;
locmax = loc;
}
}
}
int main() {
srand(time(NULL));
buildDict("/Users/XXX/Desktop/TWL06.txt");
int glomax = 0;
int i = 0;
while(true) {
string board = distBoard();
int locmax = boggle(board).size();
for(int j = 0; j < 500; j++) {
string board2 = board;
for(int k = 0; k < 2; k++)
board2 = change(board);
int loc = boggle(board2).size();
if(loc >= locmax && board != board2) {
j = 0;
board = board2;
locmax = loc;
}
}
if(glomax <= locmax) {
glomax = locmax;
cout << board << " " << glomax << " words." << endl;
}
if(++i % 10 == 0)
cout << i << endl;
}
}