解决一个流行的字谜。输入是由一些字母和单词的二维数组组成。目标是赵楚字谜中的单词,这些单词可能是水平、垂直或沿着对角线异任何方向放置的。例如求解下图:
图1-1 字谜示例
1 2 3 4 1 t h i s 2 w a t s 3 o a h g 4 f g d t
书中给出的直观算法:对单词表中的每个单词。我们检查每一个有序三元组(行,列,方向),验证单词的存在。算是直接暴力查找吧。书中后续章节有优化方法, 以后再做研究。现直观算法代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define WORD_PUZZLE_TABLE_WIDTH 4
#define WORD_PUZZLE_TABLE_HIGHT 4
/** 字谜表 */
const char word_puzzle_table[WORD_PUZZLE_TABLE_WIDTH][WORD_PUZZLE_TABLE_HIGHT] =
{
{'t', 'h', 'i', 's'},
{'w', 'a', 't', 's'},
{'o', 'a', 'h', 'g'},
{'f', 'g', 'd', 't'}
};
/** 单词表 */
const char *word_table[] = {"this", "two", "fat", "that"};
#define WORD_TABLE_LEN (sizeof(word_table) / sizeof(char*))
/** 点结构体 */
typedef struct point
{
int x;
int y;
} point;
/**
* 查找结果结构体
* pword 查找结果单词指针
* begin 单词的开始位置
* end 单词的结束位置
* note:约定于坐标轴的方式表示,如:
* 0 -----> x
* |
* |
* |y
*/
typedef struct result
{
const char *pword;
point begin;
point end;
} result;
/** 定义查找方式宏 */
#define SEARCH_BEG 1
#define LEFT_TO_RIGHT 1
#define RIGHT_TO_LEFT 2
#define TOP_TO_UPPER 3
#define UPPER_TO_TOP 4
#define MAIN_DIAGONAL 5
#define R_MAIN_DIAGONAL 6
#define COUNTER_DIAGONAL 7
#define R_COUNTER_DIAGONAL 8
#define SEARCH_END 8
/**
* 将字母c追加到字符串arras后面
* arras 待追加字符串指针
* c 待追加字母
*/
void append(char *arras, char c)
{
assert(NULL != arras);
while(*arras)
++arras;
*arras = c;
}
/**
* 查找函数
* presult_set 查找结果集
*/
void search(result *presult_set)
{
int search_way;
char str_temp[20];
int i, j, k;
int index = 0;
int flag = 0;
result temp;
asser(NULL != presult_set);
memset(str_temp, '\0', sizeof(str_temp));
/* 依次从各个方向开始查找 */
for(search_way=1; search_way<=SEARCH_END; ++search_way)
{
switch(search_way)
{
case LEFT_TO_RIGHT:
temp.begin.x = 1;
for(i=0; i<WORD_PUZZLE_TABLE_HIGHT; ++i)
{
temp.begin.y = i + 1;
for(j=0; j<WORD_PUZZLE_TABLE_WIDTH; ++j)
{
append(str_temp, word_puzzle_table[i][j]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = j + 1;
temp.end.y = i + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
}
break;
case RIGHT_TO_LEFT:
temp.begin.x = WORD_PUZZLE_TABLE_WIDTH;
for(i=WORD_PUZZLE_TABLE_HIGHT-1; i>=0; --i)
{
temp.begin.y = i + 1;
for(j=WORD_PUZZLE_TABLE_WIDTH-1; j>=0; --j)
{
append(str_temp, word_puzzle_table[i][j]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = j + 1;
temp.end.y = i + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
}
break;
case TOP_TO_UPPER:
temp.begin.y = 1;
for(i=0; i<WORD_PUZZLE_TABLE_WIDTH; ++i)
{
temp.begin.x = i + 1;
for(j=0; j<WORD_PUZZLE_TABLE_HIGHT; ++j)
{
append(str_temp, word_puzzle_table[j][i]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = i + 1;
temp.end.y = j + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
}
break;
case UPPER_TO_TOP:
temp.begin.y = WORD_PUZZLE_TABLE_HIGHT;
for(i=0; i<WORD_PUZZLE_TABLE_WIDTH; ++i)
{
temp.begin.x = i + 1;
for(j=WORD_PUZZLE_TABLE_HIGHT-1; j>=0; --j)
{
append(str_temp, word_puzzle_table[j][i]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = i + 1;
temp.end.y = j + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
}
break;
case MAIN_DIAGONAL:
temp.begin.x = 1;
temp.begin.y = 1;
for(i=0; i<WORD_PUZZLE_TABLE_HIGHT; ++i)
{
for(j=0; j<WORD_PUZZLE_TABLE_WIDTH; ++j)
{
if(i == j)
{
append(str_temp, word_puzzle_table[i][j]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = i + 1;
temp.end.y = j + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
}
if(flag)
break;
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
break;
case R_MAIN_DIAGONAL:
temp.begin.x = WORD_PUZZLE_TABLE_WIDTH;
temp.begin.y = WORD_PUZZLE_TABLE_HIGHT;
for(i=WORD_PUZZLE_TABLE_HIGHT-1; i>=0; --i)
{
for(j=WORD_PUZZLE_TABLE_WIDTH-1; j>=0; --j)
{
if(i == j)
{
append(str_temp, word_puzzle_table[i][j]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = i + 1;
temp.end.y = j + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
}
if(flag)
break;
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
break;
case COUNTER_DIAGONAL:
temp.begin.y = WORD_PUZZLE_TABLE_HIGHT;
temp.begin.x = 1;
for(i=WORD_PUZZLE_TABLE_HIGHT-1; i>=0; --i)
{
for(j=0; j<WORD_PUZZLE_TABLE_WIDTH; ++j)
{
if(i + j == WORD_PUZZLE_TABLE_WIDTH - 1)
{
append(str_temp, word_puzzle_table[i][j]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = j + 1;
temp.end.y = i + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
}
if(flag)
break;
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
break;
case R_COUNTER_DIAGONAL:
temp.begin.y = 1;
temp.begin.x = WORD_PUZZLE_TABLE_WIDTH;
for(i=0; i<WORD_PUZZLE_TABLE_HIGHT; ++i)
{
for(j=WORD_PUZZLE_TABLE_WIDTH-1; j>=0; --j)
{
if(i + j == WORD_PUZZLE_TABLE_WIDTH - 1)
{
append(str_temp, word_puzzle_table[i][j]);
for(k=0; k<WORD_TABLE_LEN; ++k)
{
if(0 == strcmp(str_temp, word_table[k]))
{
temp.pword = word_table[k];
temp.end.x = j + 1;
temp.end.y = i + 1;
presult_set[index] = temp;
flag = 1;
++index;
break;
}
}
}
if(flag)
break;
}
if(flag)
{
flag = 0;
break;
}
}
memset(str_temp, '\0', sizeof(str_temp));
break;
default:
break;
}
flag = 0;
}
}
int main()
{
result rlt_set[WORD_TABLE_LEN];
int i;
search(rlt_set);
for(i=0; i<WORD_TABLE_LEN; ++i)
printf("%s, (%d, %d)-->(%d, %d)\n", rlt_set[i].pword,
rlt_set[i].begin.x, rlt_set[i].begin.y,
rlt_set[i].end.x, rlt_set[i].end.y);
return 0;
}
</span>
运行结果: