No Nines – Solution

The challenge for this month’s Exercise is to determine whether an integer, 1 to 100, is divisible by nine or contains the digit ‘9’. It seems like an easy puzzle for a C programmer to solve, but what I found interesting was crafting the output — specifically when a number both contains ‘9’ and is divisible by nine.

For my solution, which you can view in full on GitHub, I used a series of enumerated constants to determine the return value from my no_nine() function:

enum { LEGAL, DIVIDEDBY, NINE };

The three constants are LEGAL (0) for a legal value; DIVIDEDBY (1) for a value evenly-divisible by nine; and NINE (2) for a value containing the digit ‘9’.

Here is my no_nine() function:

int no_nine(int n)
{
    char number[16];
    int r,t;

    t = LEGAL;        /* it's zero */

    /* is the number divisible by nine? */
    if( n % 9 == 0 )
        t += DIVIDEDBY;

    /* convert the number into a string */
    r = snprintf(number,16,"%d",n);
        /* test for overflow, though the size 16 is
           beyond the range of a standard int value */
    if( r > 16 )
    {
        fprintf(stderr,"Number overflow\n");
        exit(1);
    }

    /* does the digit 9 appear in the number? */
    if( strchr(number,'9') != NULL )
        t += NINE;

    /* no nines found */
    return(t);
}

The first assumption is that the number passed, n, is legal: t = LEGAL, which also initializes return variable t.

An if statement determines whether the value is evenly divisible by 9: if( n % 9 == 0 ). If so, the value of variable t is increased: t += DIVIDEDBY; But the function doesn’t stop there.

To check for the digit ‘9’, the snprintf() function converts int variable t into a string, number. The strchr() function then checks for the presence of the digit ‘9’ within the string:

if( strchr(number,'9') != NULL )

If a NULL is returned from the strchr() function, the string lacks a ‘9’ digit, so this function checks for a positive return value, in which case variable t is increased: t += NINE;

When the value of variable t is then returned to the main() function, its possible values are:

LEGAL (0), no nines
DIVIDEDBY (1), divisible by nine
NINE (2), contains the digit ‘9’
DIVIDEDBY+NINE (3), both divisible by nine and containing the digit ‘9’

In the main() function, the return value from no_nine() is compared in a complex if-else structure to output the proper string. Here is the code snippet, where x is the int tested and r is the return value from the no_nines() function:

    if( r == LEGAL )
        printf("%3d is legal\n",x);
    else
    {
        printf("%3d is illegal - ",x);
        if( r == DIVIDEDBY+NINE )
            printf("divisible by 9 and contains '9'\n");
        else if ( r == DIVIDEDBY )
            printf("divisible by 9\n");
        else
            printf("contains '9'\n");
    }

For me, the easy part of this Exercise was crafting the no_nines() function. Determining whether a value is divisible by 9 is cinchy when you know how to use the % operator. The only way I could figure out how to check for the digit ‘9’ is to convert the number to a string and then search for it.

In my first draft of the solution, the no_nines() function returned TRUE or FALSE, but then I wanted more detail in the output, so I devised the enum constants.

For the main() function, I tried to devise a more clever way to generate the “both” output string, but settled on the if-else contraption as it works. It would be nifty to craft a method to generate the "divisible by 9 and contains a '9'" string by combining output from the two other “illegal” conditions, but my brain was sapped. Perhaps you came up with a better solution?

Keep in mind that any programming solution for this challenge is valid, providing it generates the proper output.

Leave a Reply