Finding All the Pangrams

I introduced the pangram concept in last week’s Lesson. The code demonstrated how to locate 7-letter words where no letter repeats, based on the online game Spelling Bee. But a pangram need not be limited to just seven letters.

To find pangrams in the digital dictionary file, I updated the code from last week’s Lesson. I decided to keep the minimum letter length to seven, but have no maximum limit. This change required a few modifications to the code.

First, the char_scan() function is updated to include both the word to scan (char *a) and its length (int len). Further, I modified the function to check for an initial capital letter, hopefully to eliminate proper nouns. It also scans for apostrophes, which saves a lot of code in the main() function.

The main() function is updated to account for the longer pangrams and output when a new, long pangram is found. Here is the code:

2023_11_25-Lesson.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.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 char_scan(char *a,int len)
{
    int x,y;

    /* eliminate proper nouns */
    if( isupper(a[0]) )
        return(FALSE);

    /* scan the characters */
    for( x=0; x<len-2; x++ )
    {
        for( y=x+1; y<len-1; y++ )
        {
            if( a[x] == a[y] )
            {
                /* not unique */
                return(FALSE);
            }
            if( a[x] == '\'' )
                return(FALSE);
        }
    }
    return(TRUE);
}

int main()
{
    FILE *dict;
    int length,count,max;
    char word[SIZE],*r;

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

    /* scan for pangrams */
    count = max = 0;
    while( !feof(dict) )
    {
        memset(word,'\0',SIZE);        /* clear buffer */
        r = fgets(word,SIZE,dict);    /* read a word */
        if( r==NULL )
            break;
        length = strlen(word);
        if( length>7 )
        {
            if( char_scan(word,length) )
            {
                if( length > max )
                {
                    printf("%s",word);
                    max = length;
                }
                count++;
            }
        }
    }
    printf("I found %d pangrams!\n",count);

    /* close */
    fclose(dict);

    return(0);
}

In the main() function, int variable length stores the dictionary word’s letter count. If it’s greater than seven, if( length>7 ), the char_scan() function is called. When this function returns TRUE, the value of length is compared with int variable max to check for long pangrams. The long pangram word is output. Variable count increments for all discovered pangrams, count++.

Here’s a sample run:

abdomen
abdomens
abducting
abductions
abridgments
ambidextrous
ambidextrously
I found 7089 pangrams!

At least on my computer’s dictionary, the longest available pangram is ambidextrously (14 letters).

In the Spelling Bee game, a pangram is limited to only those letters supplied with one letter required. Further, the letters can repeat. In next week’s Lesson, I further update the code to better emulate the Spelling Bee puzzle.

4 thoughts on “Finding All the Pangrams

  1. I wonder whether it would be more efficient to sort the word and then scan it a single time to find duplicate consecutive letters. Did you get anywhere with the vicuña problem? I suppose you are going to do it mañana.

  2. I tried sorting the word to locate duplicates, but the code was messy. Maybe that’s just me?

    I forgot about the ñ thing. It can be fixed by adding an isalpha() test in the char_scan() function.

  3. Not sure whether this would be considered “messy”. I threw it together quickly so buglessness not guaranteed. The
    uniqueletters function creates a copy in case the original string is needed for further use.

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

    int compare_chars(const void*, const void*);
    int uniqueletters(char*);

    int main()
    {
        char word[] = “mammoth”;
        // char word[] = “penguin”;
        // char word[] = “dolphin”;
        // char word[] = “hamster”;

        int unique = uniqueletters(word);

        printf(“%s has “, word);

        if(unique == 1)
            printf(“no “);

        printf(“duplicate letters\n”);

        return EXIT_SUCCESS;
    }

    int compare_chars(const void* a, const void* b)
    {
        if(*(char*)a < *(char*)b)
            return -1;
        else if(*(char*)a > *(char*)b)
            return 1;
        else
            return 0;
    }

    int uniqueletters(char* str)
    {
        int len = strlen(str);
        char copy[len];

        strcpy(copy, str);

        qsort(copy, len, sizeof(char), compare_chars);

        for(int i = 0; i < len; i++)
        {
            if(copy[i] == copy[i+1])
                return 0;
        };
       
        return 1;
    }

Leave a Reply