String 拼字块检查
对于拼字游戏中的平铺检查,您可以制作四个5x5的字母网格,总共100个平铺。我想做一个40个水平和垂直单词都有效的例子。可用分幅集包含:String 拼字块检查,string,algorithm,data-structures,scrabble,String,Algorithm,Data Structures,Scrabble,对于拼字游戏中的平铺检查,您可以制作四个5x5的字母网格,总共100个平铺。我想做一个40个水平和垂直单词都有效的例子。可用分幅集包含: 12 x E 9 x A,I 8 x O 6xN,R,T 4 x D,L,S,U 3 x G 2 x B、C、F、H、M、P、V、W、Y、空白磁贴(通配符) 1 x K,J,Q,x,Z 有效单词词典可用(700KB)。大约有12000个5个字母的有效单词 下面是一个示例,其中所有20个水平单词都有效: Z O W I E|P I N O T Y O G I
- 12 x E
- 9 x A,I
- 8 x O
- 6xN,R,T
- 4 x D,L,S,U
- 3 x G
- 2 x B、C、F、H、M、P、V、W、Y、空白磁贴(通配符)
- 1 x K,J,Q,x,Z
Z O W I E|P I N O T
Y O G I N|O C t A D <= blank being used as 't'
X E B E C|N A L E D
W A I T E|M E R L E
V I N E R|L U T E A
---------+---------
U S N E A|K N O S P
T A V E R|J O L E D
S O F T A|I A M B I
R I D G Y|H A I T h <= blank being used as 'h'
Q U R S H|G R O U F
Z O W I E|P I N O T
Y O G I N | O C t A D我会采取悲观的观点来处理这个问题(当然是天真的)。我试图证明没有5x5解决方案,因此肯定没有四个5x5解决方案。为了证明不存在5x5解决方案,我尝试从各种可能性中构建一个。如果我的猜想失败了,我能够构造一个5x5解,那么,我就有办法构造5x5解,我会尝试构造所有(独立的)5x5解。如果至少有4个,那么我将确定某个组合是否满足字母计数限制
[Edit]Null Set已确定存在“4430974 5x5解决方案”。这些有效吗?
我的意思是,我们可以使用的字母数量有限制。此限制可以表示为边界向量BV=[9,2,2,4,…],对应于a,B,C等上的限制(您可以在Null集合的代码中看到此向量)。如果字母计数向量的每个项小于BV中的相应项,则5x5解有效。在创建5x5解决方案时,很容易检查它是否有效。也许4430974的数字可以减少,比如说减少到N
不管怎样,我们可以把这个问题表述为:在N中找到四个字母计数向量,其和等于BV。有(N,4)个可能的和(“N选择4”)。当N等于400万时,这个数字仍然在10^25左右——这不是一个令人鼓舞的数字。也许您可以搜索四个第一个项的总和为9的项,如果是,则检查第二个项的总和是否为2,以此类推
我要指出的是,在从N中选择4之后,计算是独立的,因此,如果你有一台多核机器,你可以通过并行解决方案加快计算速度
[Edit2]不过,并行化可能不会有多大区别。在这一点上,我可能会采取乐观的观点:肯定有比我预期的更多的5x5解决方案,因此最终的解决方案也可能比预期的更多。也许你不需要深入到10^25就可以找到一个。最终编辑:解决了这里有一个解决方案
GNAWN|jOULE
RACHE|EUROS
IDIOT|STEAN
PINOT|TRAvE
TRIPY|SOLES
-----+-----
HOWFF|ZEBRA
AGILE|EQUID
CIVIL|BUXOM
EVENT|RIOJA
KEDGY|ADMAN
这是一张用我的拼字游戏集制作的照片
一旦我找到了正确的方法,这个很容易找到,所以我打赌你可以通过这种方法找到更多。方法见下文
从每行和每列包含5个字母单词的字典中构造前缀树。递归地,如果给定的平铺放置为其列和行形成有效前缀,并且该平铺可用,并且下一个平铺放置有效,则该平铺放置有效。基本情况是,如果没有要放置的平铺,则它是有效的
正如格伦所说,找到所有有效的5x5板,看看其中是否有四块可以组合起来,这可能是有道理的。递归到100度听起来并不有趣
编辑:这是我的代码的第2版
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef union node node;
union node {
node* child[26];
char string[6];
};
typedef struct snap snap;
struct snap {
node* rows[5];
node* cols[5];
char tiles[27];
snap* next;
};
node* root;
node* vtrie[5];
node* htrie[5];
snap* head;
char bag[27] = {9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1,2};
const char full_bag[27] = {9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1,2};
const char order[26] = {16,23,9,25,21,22,5,10,1,6,7,12,15,2,24,3,20,13,19,11,8,17,14,0,18,4};
void insert(char* string){
node* place = root;
int i;
for(i=0;i<5;i++){
if(place->child[string[i] - 'A'] == NULL){
int j;
place->child[string[i] - 'A'] = malloc(sizeof(node));
for(j=0;j<26;j++){
place->child[string[i] - 'A']->child[j] = NULL;
}
}
place = place->child[string[i] - 'A'];
}
memcpy(place->string, string, 6);
}
void check_four(){
snap *a, *b, *c, *d;
char two_total[27];
char three_total[27];
int i;
bool match;
a = head;
for(b = a->next; b != NULL; b = b->next){
for(i=0;i<27; i++)
two_total[i] = a->tiles[i] + b->tiles[i];
for(c = b->next; c != NULL; c = c->next){
for(i=0;i<27; i++)
three_total[i] = two_total[i] + c->tiles[i];
for(d = c->next; d != NULL; d = d->next){
match = true;
for(i=0; i<27; i++){
if(three_total[i] + d->tiles[i] != full_bag[i]){
match = false;
break;
}
}
if(match){
printf("\nBoard Found!\n\n");
for(i=0;i<5;i++){
printf("%s\n", a->rows[i]->string);
}
printf("\n");
for(i=0;i<5;i++){
printf("%s\n", b->rows[i]->string);
}
printf("\n");
for(i=0;i<5;i++){
printf("%s\n", c->rows[i]->string);
}
printf("\n");
for(i=0;i<5;i++){
printf("%s\n", d->rows[i]->string);
}
exit(0);
}
}
}
}
}
void snapshot(){
snap* shot = malloc(sizeof(snap));
int i;
for(i=0;i<5;i++){
printf("%s\n", htrie[i]->string);
shot->rows[i] = htrie[i];
shot->cols[i] = vtrie[i];
}
printf("\n");
for(i=0;i<27;i++){
shot->tiles[i] = full_bag[i] - bag[i];
}
bool transpose = false;
snap* place = head;
while(place != NULL && !transpose){
transpose = true;
for(i=0;i<5;i++){
if(shot->rows[i] != place->cols[i]){
transpose = false;
break;
}
}
place = place->next;
}
if(transpose){
free(shot);
}
else {
shot->next = head;
head = shot;
check_four();
}
}
void pick(x, y){
if(y==5){
snapshot();
return;
}
int i, tile,nextx, nexty, nextz;
node* oldv = vtrie[x];
node* oldh = htrie[y];
if(x+1==5){
nexty = y+1;
nextx = 0;
} else {
nextx = x+1;
nexty = y;
}
for(i=0;i<26;i++){
if(vtrie[x]->child[order[i]]!=NULL &&
htrie[y]->child[order[i]]!=NULL &&
(tile = bag[i] ? i : bag[26] ? 26 : -1) + 1) {
vtrie[x] = vtrie[x]->child[order[i]];
htrie[y] = htrie[y]->child[order[i]];
bag[tile]--;
pick(nextx, nexty);
vtrie[x] = oldv;
htrie[y] = oldh;
bag[tile]++;
}
}
}
int main(int argc, char** argv){
root = malloc(sizeof(node));
FILE* wordlist = fopen("sowpods5letters.txt", "r");
head = NULL;
int i;
for(i=0;i<26;i++){
root->child[i] = NULL;
}
for(i=0;i<5;i++){
vtrie[i] = root;
htrie[i] = root;
}
char* string = malloc(sizeof(char)*6);
while(fscanf(wordlist, "%s", string) != EOF){
insert(string);
}
free(string);
fclose(wordlist);
pick(0,0);
return 0;
}
编辑4:这是最终产品
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef union node node;
union node {
node* child[26];
char string[6];
};
node* root;
node* vtrie[5];
node* htrie[5];
int score;
int max_score;
char block_1[27] = {4,2,0,2, 2,0,0,0,2,1,0,0,2,1,2,0,1,2,0,0,2,0,0,1,0,1,0};//ZEBRA EQUID BUXOM RIOJA ADMAN
char block_2[27] = {1,0,1,1, 4,2,2,1,3,0,1,2,0,1,1,0,0,0,0,1,0,2,1,0,1,0,0};//HOWFF AGILE CIVIL EVENT KEDGY
char block_3[27] = {2,0,1,1, 1,0,1,1,4,0,0,0,0,3,2,2,0,2,0,3,0,0,1,0,1,0,0};//GNAWN RACHE IDIOT PINOT TRIPY
//JOULE EUROS STEAN TRAVE SOLES
char bag[27] = {9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1,2};
const char full_bag[27] = {9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1,2};
const char order[26] = {16,23,9,25,21,22,5,10,1,6,7,12,15,2,24,3,20,13,19,11,8,17,14,0,18,4};
const int value[27] = {244,862,678,564,226,1309,844,765,363,4656,909,414,691,463,333,687,11998,329,218,423,536,1944,1244,4673,639,3363,0};
void insert(char* string){
node* place = root;
int i;
for(i=0;i<5;i++){
if(place->child[string[i] - 'A'] == NULL){
int j;
place->child[string[i] - 'A'] = malloc(sizeof(node));
for(j=0;j<26;j++){
place->child[string[i] - 'A']->child[j] = NULL;
}
}
place = place->child[string[i] - 'A'];
}
memcpy(place->string, string, 6);
}
void snapshot(){
static int count = 0;
int i;
for(i=0;i<5;i++){
printf("%s\n", htrie[i]->string);
}
for(i=0;i<27;i++){
printf("%c%d ", 'A'+i, bag[i]);
}
printf("\n");
if(++count>=1000){
exit(0);
}
}
void pick(x, y){
if(y==5){
if(score>max_score){
snapshot();
max_score = score;
}
return;
}
int i, tile,nextx, nexty;
node* oldv = vtrie[x];
node* oldh = htrie[y];
if(x+1==5){
nextx = 0;
nexty = y+1;
} else {
nextx = x+1;
nexty = y;
}
for(i=0;i<26;i++){
if(vtrie[x]->child[order[i]]!=NULL &&
htrie[y]->child[order[i]]!=NULL &&
(tile = bag[order[i]] ? order[i] : bag[26] ? 26 : -1) + 1) {
vtrie[x] = vtrie[x]->child[order[i]];
htrie[y] = htrie[y]->child[order[i]];
bag[tile]--;
score+=value[tile];
pick(nextx, nexty);
vtrie[x] = oldv;
htrie[y] = oldh;
bag[tile]++;
score-=value[tile];
}
}
}
int main(int argc, char** argv){
root = malloc(sizeof(node));
FILE* wordlist = fopen("sowpods5letters.txt", "r");
score = 0;
max_score = 0;
int i;
for(i=0;i<26;i++){
root->child[i] = NULL;
}
for(i=0;i<5;i++){
vtrie[i] = root;
htrie[i] = root;
}
for(i=0;i<27;i++){
bag[i] = bag[i] - block_1[i];
bag[i] = bag[i] - block_2[i];
bag[i] = bag[i] - block_3[i];
printf("%c%d ", 'A'+i, bag[i]);
}
char* string = malloc(sizeof(char)*6);
while(fscanf(wordlist, "%s", string) != EOF){
insert(string);
}
free(string);
fclose(wordlist);
pick(0,0);
return 0;
}
#包括
#包括
#包括
#包括
typedef联合节点;
联合节点{
节点*子节点[26];
字符串[6];
};
节点*根;
节点*vtrie[5];
节点*htrie[5];
智力得分;
int max_分数;
字符块_1[27]={4,2,0,2,0,0,2,1,0,0,2,1,2,0,1,2,2,0,0,2,0,0,0,0,0,1,0}//斑马马肉
字符块_2[27]={1,0,1,1,4,2,2,1,3,0,1,1,2,0,1,1,0,0,0,0,1,0,2,1,0,0,0}//HOWFF敏捷民事事件KEDGY
字符块_3[27]={2,0,1,1,1,1,4,0,0,0,0,3,2,0,2,0,3,0,0,0,1,0,0,0,0}//啃轴白痴比诺特里皮
//焦耳欧元硬脂底
炭袋[27]={9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,4,2,2,1,2};
const char full_bag[27]={9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,4,2,2,1,2};
常量字符顺序[26]={16,23,9,25,21,22,5,10,1,6,7,12,15,2,24,3,20,13,19,11,8,17,14,0,18,4};
const int value[27]={2448626785642261309844765363465690941469146914633333687119983292184235361944124446736393363,0};
空插入(字符*字符串){
节点*位置=根;
int i;
对于(i=0;ichild[string[i]-'A']==NULL){
int j;
place->child[string[i]-'A']=malloc(sizeof(node));
对于(j=0;jchild[string[i]-'A']->child[j]=NULL;
}
}
place=place->child[string[i]-“A'];
}
memcpy(place->string,string,6);
}
void快照(){
静态整数计数=0;
int i;
对于(i=0;istring);
}
对于(i=0;i=1000){
出口(0);
}
}
空拾取(x,y){
如果(y==5){
如果(分数>最大分数){
快照();
最大分数=分数;
}
返回;
}
int i、tile、nextx、nexty;
节点*oldv=vtrie[x];
节点*oldh=htrie[y];
如果(x+1==5){
nextx=0;
nexty=y+1;
}否则{
nextx=x+1;
nexty=y;
}
对于(i=0;ichild[order[i]]!=NULL&&
htrie[y]>child[order[i]!=NULL&&
(瓷砖=袋子[订单[i]]?订单[i]:袋子[26]?26:-1)+1){
vtrie[x]=vtrie[x]>child[order[i]];
htrie[y]=htrie[y]>child[order[i]];
包[瓦]——;
分数+=价值[瓷砖];
拾取(nextx、nexty);
vtrie[x]=oldv;
htrie[y]=oldh;
包[瓷砖]+;
分数-=价值[瓷砖];
}
}
}
int main(int argc,字符**argv){
root=malloc(sizeof(node));
文件*字表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef union node node;
union node {
node* child[26];
char string[6];
};
node* root;
node* vtrie[5];
node* htrie[5];
int score;
int max_score;
char block_1[27] = {4,2,0,2, 2,0,0,0,2,1,0,0,2,1,2,0,1,2,0,0,2,0,0,1,0,1,0};//ZEBRA EQUID BUXOM RIOJA ADMAN
char block_2[27] = {1,0,1,1, 4,2,2,1,3,0,1,2,0,1,1,0,0,0,0,1,0,2,1,0,1,0,0};//HOWFF AGILE CIVIL EVENT KEDGY
char block_3[27] = {2,0,1,1, 1,0,1,1,4,0,0,0,0,3,2,2,0,2,0,3,0,0,1,0,1,0,0};//GNAWN RACHE IDIOT PINOT TRIPY
//JOULE EUROS STEAN TRAVE SOLES
char bag[27] = {9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1,2};
const char full_bag[27] = {9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1,2};
const char order[26] = {16,23,9,25,21,22,5,10,1,6,7,12,15,2,24,3,20,13,19,11,8,17,14,0,18,4};
const int value[27] = {244,862,678,564,226,1309,844,765,363,4656,909,414,691,463,333,687,11998,329,218,423,536,1944,1244,4673,639,3363,0};
void insert(char* string){
node* place = root;
int i;
for(i=0;i<5;i++){
if(place->child[string[i] - 'A'] == NULL){
int j;
place->child[string[i] - 'A'] = malloc(sizeof(node));
for(j=0;j<26;j++){
place->child[string[i] - 'A']->child[j] = NULL;
}
}
place = place->child[string[i] - 'A'];
}
memcpy(place->string, string, 6);
}
void snapshot(){
static int count = 0;
int i;
for(i=0;i<5;i++){
printf("%s\n", htrie[i]->string);
}
for(i=0;i<27;i++){
printf("%c%d ", 'A'+i, bag[i]);
}
printf("\n");
if(++count>=1000){
exit(0);
}
}
void pick(x, y){
if(y==5){
if(score>max_score){
snapshot();
max_score = score;
}
return;
}
int i, tile,nextx, nexty;
node* oldv = vtrie[x];
node* oldh = htrie[y];
if(x+1==5){
nextx = 0;
nexty = y+1;
} else {
nextx = x+1;
nexty = y;
}
for(i=0;i<26;i++){
if(vtrie[x]->child[order[i]]!=NULL &&
htrie[y]->child[order[i]]!=NULL &&
(tile = bag[order[i]] ? order[i] : bag[26] ? 26 : -1) + 1) {
vtrie[x] = vtrie[x]->child[order[i]];
htrie[y] = htrie[y]->child[order[i]];
bag[tile]--;
score+=value[tile];
pick(nextx, nexty);
vtrie[x] = oldv;
htrie[y] = oldh;
bag[tile]++;
score-=value[tile];
}
}
}
int main(int argc, char** argv){
root = malloc(sizeof(node));
FILE* wordlist = fopen("sowpods5letters.txt", "r");
score = 0;
max_score = 0;
int i;
for(i=0;i<26;i++){
root->child[i] = NULL;
}
for(i=0;i<5;i++){
vtrie[i] = root;
htrie[i] = root;
}
for(i=0;i<27;i++){
bag[i] = bag[i] - block_1[i];
bag[i] = bag[i] - block_2[i];
bag[i] = bag[i] - block_3[i];
printf("%c%d ", 'A'+i, bag[i]);
}
char* string = malloc(sizeof(char)*6);
while(fscanf(wordlist, "%s", string) != EOF){
insert(string);
}
free(string);
fclose(wordlist);
pick(0,0);
return 0;
}
O(n * n/10 * n/10 * n/100 * n/100 * n/1000 * n/1000 ...
which for 12000 elements acts something like n^4 algorithm
AQFED, ZQABE, EDQDE, ELQUO
this means there are two valid positionings of those:
xZxxx
AQFED
xAxxx ---> this limits our search for words that contain [ABDEFZ] as the second letter
xBxxx
xExxx
same for the other
EDQDE ---> this limits our search for words that contain [EDLU] as the third letter
ELQUO
all appropriate words are in union of those two conditions
3736 2x2 solutions
8812672 3x3 solutions
The 1000th 4x4 solution is
A A H S
A C A I
L A I R
S I R E
The 1000th 5x5 solution is
A A H E D
A B U N A
H U R S T
E N S U E
D A T E D
The 1000th 2x4x4 solution is
A A H S | A A H S
A B A C | A B A C
H A I R | L E K U
S C R Y | S T E D
--------+--------
D E E D | D E E M
E I N E | I N T I
E N O L | O V E R
T E L T | L Y N E