mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-14 08:01:38 +01:00
add dict_makeIndex(). Works, but only for depth==1 so far (A, not AA or AAA).
This commit is contained in:
parent
b62fe13c97
commit
f2c4e39cd4
4 changed files with 155 additions and 32 deletions
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue