Instead all found answers now appear alphabetically before the blanks
corresponding to all unfound answers.
Part of implementing this was adding new of_length interfaces to dict
in place (or in addition) to the previous by_length interfaces. The
new interfaces are much more useful, (allowing length-limited queries
without any implicit looping).
-trie_count (trie_t *trie,
- trie_predicate_t predicate)
+trie_count_if (trie_t *trie,
+ trie_predicate_t predicate)
- if ((predicate) (trie))
+ if (predicate == NULL || (predicate) (trie))
count = 1;
for (i = 0; i < 26; i++) {
if (trie->next[i] == NULL)
continue;
count = 1;
for (i = 0; i < 26; i++) {
if (trie->next[i] == NULL)
continue;
- count += trie_count (trie->next[i], predicate);
+ count += trie_count_if (trie->next[i], predicate);
}
return count;
}
static int
}
return count;
}
static int
-trie_for_each (trie_t *trie,
- string_t *string,
- trie_predicate_t predicate,
- int length,
- int min_length,
- int max_length,
- dict_action_t action,
- void *closure)
+trie_for_each_of_length_if (trie_t *trie,
+ dict_action_t action,
+ void *closure,
+ int min_length,
+ int max_length,
+ trie_predicate_t predicate,
+ string_t *string,
+ int length)
+
c = TRIE_INDEX_TO_CHAR (i);
string_append_char (string, c);
c = TRIE_INDEX_TO_CHAR (i);
string_append_char (string, c);
- count += trie_for_each (trie->next[i], string, predicate,
- length + 1, min_length, max_length,
- action, closure);
+ count += trie_for_each_of_length_if (trie->next[i],
+ action, closure,
+ min_length, max_length,
+ predicate,
+ string, length + 1);
-dict_count (dict_t *dict,
- dict_entry_predicate_t predicate)
-{
- dict_entry_predicate = predicate;
- return trie_count (dict, dict_predicate);
-}
-
-int
-dict_for_each_if (dict_t *dict,
- dict_action_t action,
- void *closure,
- dict_entry_predicate_t predicate)
-
+dict_count_if (dict_t *dict,
+ dict_entry_predicate_t predicate)
- int count;
- string_t string;
-
- string_init (&string);
-
dict_entry_predicate = predicate;
dict_entry_predicate = predicate;
- count = trie_for_each (dict, &string, dict_predicate,
- 0, 0, -1, action, closure);
-
- string_fini (&string);
-
- return count;
+ return trie_count_if (dict, dict_predicate);
-dict_for_each (dict_t *dict,
- dict_action_t action,
- void *closure)
+dict_count (dict_t *dict)
- return dict_for_each_if (dict, action, closure, NULL);
+ return dict_count_if (dict, NULL);
-dict_for_each_by_length_if (dict_t *dict,
+dict_for_each_of_length_if (dict_t *dict,
dict_action_t action,
void *closure,
dict_action_t action,
void *closure,
+ int min_length,
+ int max_length,
dict_entry_predicate_t predicate)
{
dict_entry_predicate_t predicate)
{
- int length, total, words, count = 0;
string_t string;
string_init (&string);
dict_entry_predicate = predicate;
string_t string;
string_init (&string);
dict_entry_predicate = predicate;
- total = trie_count (dict, dict_predicate);
-
- length = 1;
- do {
- words = trie_for_each (dict, &string, dict_predicate,
- 0, length, length,
- action, closure);
- if (words)
- count += words;
- length++;
- } while (count < total);
+ count = trie_for_each_of_length_if (dict,
+ action, closure,
+ min_length, max_length,
+ dict_predicate,
+ &string, 0);
-dict_for_each_by_length (dict_t *dict,
+dict_for_each_of_length (dict_t *dict,
+ void *closure,
+ int min_length,
+ int max_length)
- return dict_for_each_by_length_if (dict, action, closure, NULL);
+ return dict_for_each_of_length_if (dict,
+ action, closure,
+ min_length, max_length,
+ NULL);
+}
+
+int
+dict_for_each_if (dict_t *dict,
+ dict_action_t action,
+ void *closure,
+ dict_entry_predicate_t predicate)
+
+{
+ return dict_for_each_of_length_if (dict,
+ action, closure,
+ 0, 0,
+ predicate);
+}
+
+int
+dict_for_each (dict_t *dict,
+ dict_action_t action,
+ void *closure)
+{
+ return dict_for_each_if (dict, action, closure, NULL);
}
static void
dict_action_print (void *closure, char *word, dict_entry_t *entry)
{
}
static void
dict_action_print (void *closure, char *word, dict_entry_t *entry)
{
- int *length_of_last = closure;
- int length = strlen (word);
- if (length == *length_of_last)
+ if (*first)
+ *first = 0;
+ else
- else if (*length_of_last)
- printf("\n");
-
- *length_of_last = length;
-dict_print (dict_t *dict)
+dict_print_of_length_if (dict_t *dict,
+ int min_length,
+ int max_length,
+ dict_entry_predicate_t predicate)
- int length_of_last = 0;
- return dict_for_each (dict,
- dict_action_print, &length_of_last);
+ return dict_for_each_of_length_if (dict,
+ dict_action_print, &first,
+ min_length, max_length,
+ predicate);
-dict_print_by_length (dict_t *dict)
+dict_print_by_length_if (dict_t *dict,
+ dict_entry_predicate_t predicate)
- int length_of_last = 0;
+ int length, total, words, count = 0;
+
+ total = dict_count_if (dict, predicate);
+
+ length = 1;
+ do {
+ words = dict_print_of_length_if (dict, length, length, predicate);
+ if (words) {
+ count += words;
+ printf ("\n");
+ }
+ length++;
+ } while (count < total);
- return dict_for_each_by_length (dict,
- dict_action_print, &length_of_last);
+ return count;
+}
+
+int
+dict_print_of_length (dict_t *dict,
+ int min_length,
+ int max_length)
+{
+ return dict_print_of_length_if (dict, min_length, max_length, NULL);
}
int
dict_print_if (dict_t *dict,
dict_entry_predicate_t predicate)
{
}
int
dict_print_if (dict_t *dict,
dict_entry_predicate_t predicate)
{
- int length_of_last = 0;
-
- return dict_for_each_if (dict,
- dict_action_print, &length_of_last,
- predicate);
+ return dict_print_of_length_if (dict, 0, 0, predicate);
-dict_print_by_length_if (dict_t *dict,
- dict_entry_predicate_t predicate)
+dict_print (dict_t *dict)
- int length_of_last = 0;
-
- return dict_for_each_by_length_if (dict,
- dict_action_print, &length_of_last,
- predicate);
+ return dict_print_if (dict, NULL);
(*dict_entry_predicate_t) (dict_entry_t entry);
int
(*dict_entry_predicate_t) (dict_entry_t entry);
int
-dict_count (dict_t *dict,
- dict_entry_predicate_t predicate);
+dict_count_if (dict_t *dict,
+ dict_entry_predicate_t predicate);
+
+int
+dict_count (dict_t *dict);
/* Querying a dictionary entry. The dict interface uses 1 bit.
* All of the remaining bits are available for application use.
/* Querying a dictionary entry. The dict interface uses 1 bit.
* All of the remaining bits are available for application use.
dict_print (dict_t *dict);
int
dict_print (dict_t *dict);
int
-dict_print_by_length (dict_t *dict);
+dict_print_of_length (dict_t *dict,
+ int min_length,
+ int max_length);
int
dict_print_if (dict_t *dict,
dict_entry_predicate_t predicate);
int
dict_print_if (dict_t *dict,
dict_entry_predicate_t predicate);
+int
+dict_print_of_length_if (dict_t *dict,
+ int min_length,
+ int max_length,
+ dict_entry_predicate_t predicate);
+
int
dict_print_by_length_if (dict_t *dict,
dict_entry_predicate_t predicate);
int
dict_print_by_length_if (dict_t *dict,
dict_entry_predicate_t predicate);
-dict_for_each_by_length (dict_t *dict,
+dict_for_each_of_length (dict_t *dict,
+ void *closure,
+ int min_length,
+ int max_length);
int
dict_for_each_if (dict_t *dict,
int
dict_for_each_if (dict_t *dict,
dict_entry_predicate_t predicate);
int
dict_entry_predicate_t predicate);
int
-dict_for_each_by_length_if (dict_t *dict,
+dict_for_each_of_length_if (dict_t *dict,
dict_action_t action,
void *closure,
dict_action_t action,
void *closure,
+ int min_length,
+ int max_length,
dict_entry_predicate_t predicate);
/* Character-by-character perusal of the dictionary */
dict_entry_predicate_t predicate);
/* Character-by-character perusal of the dictionary */
bag_t bag;
dict_t dict;
dict_t solution;
bag_t bag;
dict_t dict;
dict_t solution;
GooCanvasItem *solution_item;
gboolean done;
} rack_t;
GooCanvasItem *solution_item;
gboolean done;
} rack_t;
*y += (LETTER_SIZE + LETTER_PAD);
}
*y += (LETTER_SIZE + LETTER_PAD);
}
+typedef enum dict_paint_cursor_show
+{
+ DICT_PAINT_CURSOR_SHOW_FOUND,
+ DICT_PAINT_CURSOR_SHOW_UNFOUND_BLANKS,
+ DICT_PAINT_CURSOR_SHOW_ALL
+} dict_paint_cursor_show_t;
+
typedef struct _dict_paint_cursor
{
cairo_t *cr;
typedef struct _dict_paint_cursor
{
cairo_t *cr;
int y;
int max_column_width;
int max_y;
int y;
int max_column_width;
int max_y;
+ dict_paint_cursor_show_t show;
} dict_paint_cursor_t;
static void
} dict_paint_cursor_t;
static void
dict_paint_cursor_t *cursor = closure;
cairo_t *cr = cursor->cr;
double new_x, new_y;
dict_paint_cursor_t *cursor = closure;
cairo_t *cr = cursor->cr;
double new_x, new_y;
+ int found, show_blanks = FALSE;
if (strlen (word) < 3)
return;
if (strlen (word) < 3)
return;
- cairo_move_to (cr, cursor->x, cursor->y);
- if (*entry & RACK_DICT_ENTRY_FOUND || cursor->show_all) {
- if (*entry & RACK_DICT_ENTRY_FOUND)
- cairo_set_source_rgb (cr, 0, 0, 0); /* black */
- else
+ found = *entry & RACK_DICT_ENTRY_FOUND;
+
+ cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+
+ switch (cursor->show) {
+ case DICT_PAINT_CURSOR_SHOW_FOUND:
+ if (! found)
+ return;
+ break;
+ case DICT_PAINT_CURSOR_SHOW_UNFOUND_BLANKS:
+ if (found)
+ return;
+ show_blanks = TRUE;
+ break;
+ case DICT_PAINT_CURSOR_SHOW_ALL:
+ if (! found)
cairo_set_source_rgb (cr, 1, 0, 0); /* red */
cairo_set_source_rgb (cr, 1, 0, 0); /* red */
- cairo_show_text (cr, word);
- } else {
+ break;
+ }
+
+ cairo_move_to (cr, cursor->x, cursor->y);
+ if (show_blanks) {
int i, length = strlen (word);
for (i = 0; i < length; i++)
cairo_show_text (cr, "_");
int i, length = strlen (word);
for (i = 0; i < length; i++)
cairo_show_text (cr, "_");
+ } else {
+ cairo_show_text (cr, word);
}
cairo_get_current_point (cr, &new_x, &new_y);
if (new_x > cursor->max_column_width)
}
cairo_get_current_point (cr, &new_x, &new_y);
if (new_x > cursor->max_column_width)
{
rack_t *rack = closure;
dict_paint_cursor_t cursor;
{
rack_t *rack = closure;
dict_paint_cursor_t cursor;
cairo_save (cr);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
cairo_save (cr);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
cursor.max_column_width = 0;
cursor.max_y = height;
cursor.max_column_width = 0;
cursor.max_y = height;
- cursor.show_all = rack->done;
-
- dict_for_each_by_length (&rack->solution,
- dict_paint_action,
- &cursor);
+ length = 1;
+ count = 0;
+ do {
+ if (rack->done)
+ cursor.show = DICT_PAINT_CURSOR_SHOW_ALL;
+ else
+ cursor.show = DICT_PAINT_CURSOR_SHOW_FOUND;
+ count += dict_for_each_of_length (&rack->solution,
+ dict_paint_action, &cursor,
+ length, length);
+ if (! rack->done) {
+ cursor.show = DICT_PAINT_CURSOR_SHOW_UNFOUND_BLANKS;
+ dict_for_each_of_length (&rack->solution,
+ dict_paint_action, &cursor,
+ length, length);
+ }
+ length++;
+ } while (count < rack->solution_total);
dict_add_words_from_file (&rack->dict, "words.txt");
dict_init (&rack->solution);
dict_add_words_from_file (&rack->dict, "words.txt");
dict_init (&rack->solution);
+ rack->solution_total = 0;
for (i = 0; i < MAX_TILES; i++)
rack->tiles[i] = tile_create (root, 'A', i);
for (i = 0; i < MAX_TILES; i++)
rack->tiles[i] = tile_create (root, 'A', i);
dict_init (&rack->solution);
subanagram_expand (word, &rack->dict, &rack->solution);
dict_init (&rack->solution);
subanagram_expand (word, &rack->dict, &rack->solution);
+ rack->solution_total = dict_count (&rack->solution);
goo_canvas_item_simple_changed (GOO_CANVAS_ITEM_SIMPLE (rack->solution_item), FALSE);
}
goo_canvas_item_simple_changed (GOO_CANVAS_ITEM_SIMPLE (rack->solution_item), FALSE);
}