add dict_makeIndex(). Works, but only for depth==1 so far (A, not AA or AAA).

This commit is contained in:
Eric House 2011-10-26 07:10:50 -07:00
parent b62fe13c97
commit f2c4e39cd4
4 changed files with 155 additions and 32 deletions

View file

@ -639,6 +639,30 @@ dict_super_follow( const DictionaryCtxt* dict, array_edge* in )
return result;
} /* dict_super_follow */
static array_edge*
dict_super_edge_with_tile( const DictionaryCtxt* dict, array_edge* from,
Tile tile )
{
for ( ; ; ) {
Tile candidate = EDGETILE(dict,from);
if ( candidate == tile ) {
break;
}
if ( IS_LAST_EDGE(dict, from ) ) {
from = NULL;
break;
}
#ifdef NODE_CAN_4
from += dict->nodeSize;
#else
from += 3;
#endif
}
return from;
} /* edge_with_tile */
void
dict_super_init( DictionaryCtxt* dict )
{
@ -647,6 +671,7 @@ dict_super_init( DictionaryCtxt* dict )
dict->func_dict_getTopEdge = dict_super_getTopEdge;
dict->func_dict_index_from = dict_super_index_from;
dict->func_dict_follow = dict_super_follow;
dict->func_dict_edge_with_tile = dict_super_edge_with_tile;
dict->func_dict_getShortName = dict_getName;
} /* dict_super_init */
@ -786,6 +811,40 @@ dict_getWord( const DictionaryCtxt* dict, DictWord* word, WordFinder finder )
return success;
}
static XP_Bool
findStartsWith( const DictionaryCtxt* dict, Tile* tiles, XP_U16 nTiles,
array_edge** edges, XP_U16* nEdgesP )
{
XP_Bool success = XP_TRUE;
XP_U16 nEdges = 0;
array_edge* edge = dict_getTopEdge( dict );
while ( nTiles-- > 0 ) {
Tile tile = *tiles++;
edge = dict_edge_with_tile( dict, edge, tile );
if ( NULL == edge ) {
success = XP_FALSE;
break;
}
edges[nEdges++] = edge;
edge = dict_follow( dict, edge );
}
*nEdgesP = nEdges;
return success;
}
static XP_Bool
wordsEqual( array_edge** edges1, XP_U16 nEdges1,
array_edge** edges2, XP_U16 nEdges2 )
{
XP_Bool success = nEdges1 == nEdges2;
if ( success ) {
success = 0 == memcmp( edges1, edges2, nEdges1 * sizeof(edges1[0]) );
}
return success;
}
XP_U32
dict_countWords( const DictionaryCtxt* dict )
{
@ -802,6 +861,71 @@ dict_countWords( const DictionaryCtxt* dict )
return count;
}
void
dict_makeIndex( const DictionaryCtxt* dict, XP_U16 depth,
DictIndex* indices, XP_U16 count )
{
XP_USE( indices );
XP_ASSERT( depth == 1 ); /* so far */
XP_U16 ii, needCount;
XP_U16 nextIndex = 0;
XP_U16 nFaces = dict_numTileFaces( dict );
XP_Bool hasBlank = dict_hasBlankTile( dict );
if ( hasBlank ) {
--nFaces;
}
for ( ii = 1, needCount = nFaces; ii < depth; ++ii ) {
needCount *= nFaces;
}
XP_ASSERT( needCount <= count );
/* For each tile string implied by depth (A if depth == 1, AAA if == 3 ),
* find the first word starting with that IF EXISTS. If it does, find its
* index. As an optimization, find index starting with the previous word.
*/
DictWord firstWord;
if ( dict_firstWord( dict, &firstWord ) ) {
array_edge* prevEdges[MAX_COLS];
indicesToEdges( dict, &firstWord, prevEdges );
XP_U16 prevNEdges = firstWord.nTiles;
DictIndex index = 0;
Tile tiles[1];
nFaces = dict_numTileFaces( dict );
for ( tiles[0] = 0; tiles[0] < nFaces; ++tiles[0] ) {
if ( hasBlank && tiles[0] == dict_getBlankTile( dict ) ) {
continue;
}
array_edge* curEdges[MAX_COLS];
XP_U16 curNEdges;
if ( !findStartsWith( dict, tiles, 1, curEdges, &curNEdges ) ) {
indices[nextIndex++] = NO_INDEX;
} else {
XP_ASSERT( curNEdges == depth );
if ( ! ISACCEPTING( dict, curEdges[curNEdges-1] ) ) {
if ( !nextWord( dict, curEdges, &curNEdges ) ) {
XP_ASSERT( 0 );
}
}
if ( wordsEqual( curEdges, curNEdges, prevEdges, prevNEdges ) ) {
XP_ASSERT( index == 0 );
} else {
/* Walk the prev word forward until they're the same */
while ( nextWord( dict, prevEdges, &prevNEdges ) ) {
++index;
if ( wordsEqual( curEdges, curNEdges, prevEdges, prevNEdges ) ) {
break;
}
}
}
indices[nextIndex++] = index;
}
}
}
}
XP_Bool
dict_firstWord( const DictionaryCtxt* dict, DictWord* word )
{

View file

@ -73,6 +73,8 @@ struct DictionaryCtxt {
array_edge* p_edge );
array_edge* (*func_dict_follow)( const DictionaryCtxt* dict,
array_edge* in );
array_edge* (*func_dict_edge_with_tile)( const DictionaryCtxt* dict,
array_edge* from, Tile tile );
const XP_UCHAR* (*func_dict_getShortName)( const DictionaryCtxt* dict );
array_edge* topEdge;
@ -135,6 +137,7 @@ struct DictionaryCtxt {
#define dict_getTopEdge(d) (*((d)->func_dict_getTopEdge))(d)
#define dict_index_from(d,e) (*((d)->func_dict_index_from))(d,e)
#define dict_follow(d,e) (*((d)->func_dict_follow))(d,e)
#define dict_edge_with_tile(d,e,t) (*((d)->func_dict_edge_with_tile))(d,e,t)
#define dict_getShortName(d) (*((d)->func_dict_getShortName))(d)
#ifdef NODE_CAN_4
@ -206,14 +209,18 @@ void dict_splitFaces( DictionaryCtxt* dict, const XP_U8* bytes,
#ifdef XWFEATURE_WALKDICT
/* API for iterating over a dict */
typedef XP_U32 DictIndex;
#define NO_INDEX 0xFFFFFFFF
typedef struct _DictWord {
XP_U32 wordCount;
XP_U32 index;
DictIndex index;
XP_U16 nTiles;
XP_U32 indices[MAX_COLS];
} DictWord;
XP_U32 dict_countWords( const DictionaryCtxt* dict );
void dict_makeIndex( const DictionaryCtxt* dict, XP_U16 depth,
DictIndex* indices, XP_U16 count );
XP_Bool dict_firstWord( const DictionaryCtxt* dict, DictWord* word );
XP_Bool dict_lastWord( const DictionaryCtxt* dict, DictWord* word );
XP_Bool dict_getNextWord( const DictionaryCtxt* dict, DictWord* word );
@ -223,7 +230,7 @@ XP_Bool dict_getNthWord( const DictionaryCtxt* dict, DictWord* word,
void dict_wordToString( const DictionaryCtxt* dict, const DictWord* word,
XP_UCHAR* buf, XP_U16 buflen );
#endif
#endif /* XWFEATURE_WALKDICT */
#ifdef CPLUS
}

View file

@ -121,8 +121,6 @@ struct EngineCtxt {
static void findMovesOneRow( EngineCtxt* engine );
static Tile localGetBoardTile( EngineCtxt* engine, XP_U16 col,
XP_U16 row, XP_Bool substBlank );
static array_edge* edge_with_tile( const DictionaryCtxt* dict,
array_edge* from, Tile tile );
static XP_Bool scoreQualifies( EngineCtxt* engine, XP_U16 score );
static void findMovesForAnchor( EngineCtxt* engine, XP_S16* prevAnchor,
XP_U16 col, XP_U16 row ) ;
@ -590,7 +588,7 @@ lookup( const DictionaryCtxt* dict, array_edge* edge, Tile* buf,
{
while ( edge != NULL ) {
Tile targetTile = buf[tileIndex];
edge = edge_with_tile( dict, edge, targetTile );
edge = dict_edge_with_tile( dict, edge, targetTile );
if ( edge == NULL ) { /* tile not available out of this node */
return XP_FALSE;
} else {
@ -982,7 +980,7 @@ extendRight( EngineCtxt* engine, Tile* tiles, XP_U16 tileLength,
}
}
} else if ( (edge = edge_with_tile( dict, edge, tile ) ) != NULL ) {
} else if ( (edge = dict_edge_with_tile( dict, edge, tile ) ) != NULL ) {
accepting = ISACCEPTING( dict, edge );
extendRight( engine, tiles, tileLength, dict_follow(dict, edge),
accepting, firstCol, col+1, row );
@ -1334,34 +1332,10 @@ scoreQualifies( EngineCtxt* engine, XP_U16 score )
return qualifies;
} /* scoreQualifies */
static array_edge*
edge_with_tile( const DictionaryCtxt* dict, array_edge* from, Tile tile )
{
for ( ; ; ) {
Tile candidate = EDGETILE(dict,from);
if ( candidate == tile ) {
break;
}
if ( IS_LAST_EDGE(dict, from ) ) {
from = NULL;
break;
}
#ifdef NODE_CAN_4
from += dict->nodeSize;
#else
from += 3;
#endif
}
return from;
} /* edge_with_tile */
static array_edge*
edge_from_tile( const DictionaryCtxt* dict, array_edge* from, Tile tile )
{
array_edge* edge = edge_with_tile( dict, from, tile );
array_edge* edge = dict_edge_with_tile( dict, from, tile );
if ( edge != NULL ) {
edge = dict_follow( dict, edge );
}

View file

@ -955,7 +955,7 @@ walk_dict_test( const DictionaryCtxt* dict )
fprintf( stderr, "testing getNth\n" );
int ii;
for ( ii = 0 ; ii < 1000; ++ii ) {
for ( ii = 0 ; ii < 100; ++ii ) {
long index = XP_RANDOM() % count;
if ( dict_getNthWord( dict, &word, index ) ) {
XP_ASSERT( word.index == index );
@ -967,6 +967,24 @@ walk_dict_test( const DictionaryCtxt* dict )
}
}
DictIndex indices[26];
dict_makeIndex( dict, 1, indices, VSIZE(indices) );
for ( ii = 0; ii < VSIZE(indices); ++ii ) {
DictIndex index = indices[ii];
if ( NO_INDEX == index ) {
continue;
} else if ( dict_getNthWord( dict, &word, indices[ii] ) ) {
XP_ASSERT( word.index == indices[ii] );
XP_UCHAR buf1[64];
dict_wordToString( dict, &word, buf1, VSIZE(buf1) );
XP_UCHAR buf2[64] = {0};
if ( ii > 0 && dict_getNthWord( dict, &word, indices[ii]-1 ) ) {
dict_wordToString( dict, &word, buf2, VSIZE(buf2) );
}
fprintf( stderr, "%d: index: %ld; word: %s (prev: %s)\n", ii, indices[ii], buf1, buf2 );
}
}
exit( 0 );
}
#else