Almost a Spelling Bee-Like Scan

Scanning the digital dictionary is fun, but it’s gone on way too long! I was going to end this series with code that solves the Spelling Bee game, but decided to end things with this Lesson. This final post scans the dictionary for words that match a given clutch of characters.

Last week’s Lesson focused on pangrams. For this week’s update, I sought to match just a collection of seven letters, those shown in Figure 1.

Figure 1. Seven tiles from the Spelling Bee game. One of the pangrams is WARPING, which uses all seven letters.

The updated code reads though the dictionary, plucking out one word at a time. Whan a word is longer than four characters, a scan is made to match letters A, G, I, N, P, R, or W. The word must be composed only of these letters in any combination. Any other letter (or character) disqualifies the word. These letters are set in the declaration of variable format_string[] at the start of the code.

The secret to weeding out specific letters is the sscanf() function. This function uses the format string specified to filter the dictionary word stored in variable word[]. If the dictionary word contains only the letters listed, the resulting word is saved in the match[] buffer. These two buffers are compared to thin out partial matches. When they fully match, the word is output and tallied.

You can click here to read more about how the scanf() function is used to filter words. It’s a seldom-used feature of this function, but one that works wonderfully for my Spelling Bee/dictionary filter. In the code, I used the sscanf() version of the function, which scans a buffer and not standard input.

2023_12_02-Lesson-a.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* this code assumes the following path is valid */
#define DICTIONARY "/usr/share/dict/words"
#define SIZE 32
#define TRUE 1
#define FALSE 0

int main()
{
    FILE *dict;
    int length,count;
    char word[SIZE],*r,match[SIZE];
    const char format_string[] = "%[aginprw]";

    /* open the dictionary */
    dict = fopen(DICTIONARY,"r");
    if( dict==NULL )
    {
        fprintf(stderr,"Unable to open %s\n",DICTIONARY);
        exit(1);
    }

    /* scan for matching words */
    count = 0;
    while( !feof(dict) )
    {
        memset(word,'\0',SIZE);        /* clear buffer */
        memset(match,'\0',SIZE);
        r = fgets(word,SIZE,dict);    /* read a word */
        if( r==NULL )
            break;

        /* remove newline */
        r = word;
        while(*r)
        {
            if( *r=='\n' )
            {
                *r = '\0';
                break;
            }
            r++;
        }

        /* process the words */
        length = strlen(word);
        /* greater than four letters */
        if( length>4 )
        {
            sscanf(word,format_string,match);
            if( strcmp(word,match)==0 )
            {
                printf("%s\n",word);
                count++;
            }
        }
    }
    printf("I found %d solutions!\n",count);

    /* close */
    fclose(dict);

    return(0);
}

In this code, I added a routine to remove the newline from the word read from the dictionary. This step is necessary to match the word generated by the sscanf() function, which doesn’t append the newline.

Here’s a sample run:

again
aging
agrarian
airing
angina
aping
...
wiping
wiring
wrapping
wring
wringing
I found 82 solutions!

Not all of these words match the Spelling Bee solutions. The code doesn’t check for the required character (W in this example). More code could be added. In fact, I’ll probably do so on my own, though it seems like an obsession.

You can click here for a version of this code that allows you to input the string of characters to match. I really got carried away with it, doing all sorts of error-checking and nerfing. I may continue coding that version of the program to prompt for the key letter and identify pangrams. But for now, my dictionary-reading series has concluded.

Leave a Reply