Spelling Numbers – Solution

The task for this month’s Exercise is to write code that outputs strings for number values, 0 through 100. Your goal is to be clever with your solution, something that took me a few versions to get correct.

In English, similar to other languages, the verbal output for numbers follows a pattern. Three groups are apparent: single digits, teens, and multiples of ten that follow. The multiples of ten are combined with the single digits to generate the between values, such as “twenty-one,” “twenty-two,” and so on. Any exceptions can be pulled out in the code.

To craft my solution, I created three string arrays:

char *ones[10] = { "one", "two", "three", "four",
                   "five", "six", "seven", "eight",
                   "nine", "ten" };
char *teens[9] = { "eleven", "twelve", "thirteen",
                   "fourteen", "fifteen", "sixteen",
                   "seventeen", "eighteen", "nineteen" };
char *tens[8] = { "twenty", "thirty", "forty",
                  "fifty", "sixty", "seventy",
                  "eighty", "ninety" };

Each of these arrays handle the three number patterns. I could have tried to be clever with sixteen, seventeen, eighteen, and nineteen, but the effort didn’t seem worthy.

For values 0 and 100, I coded special exceptions in my solution:

if( n==0 )
    return("zero");
if( n==100 )
    return("one hundred");

These statements are followed by a series of if tests that work through the other patterns. The key, however, was merging the tens[] strings with the ones[] strings for values 20 and above. Here’s my solution:

2020_09-Exercise.c

#include <stdio.h>

/* return string representing integers 0 through 100 */
char *verbal(int n)
{
    char *ones[10] = { "one", "two", "three", "four",
                       "five", "six", "seven", "eight",
                       "nine", "ten" };
    char *teens[9] = { "eleven", "twelve", "thirteen",
                       "fourteen", "fifteen", "sixteen",
                       "seventeen", "eighteen", "nineteen" };
    char *tens[8] = { "twenty", "thirty", "forty",
                      "fifty", "sixty", "seventy",
                      "eighty", "ninety" };
    int dec,uns;
    static char buffer[17];

    /* no need for if-else with returns */
        /* elimninate 0 and 100 */
    if( n==0 )
        return("zero");
    if( n==100 )
        return("one hundred");
    /* process ones */
    if( n<11 )
        return(ones[n-1]);
    /* process teens */
    if( n<20 )
        return(teens[n-11]);
    /* process the rest */
        /* get the ten multiple */
    dec = (n - 20) / 10;
    uns = (n - 20) % 10 - 1;
        /* pull out tens */
    if( uns < 0 )
        return(tens[dec]);
        /* build string for everything else */
    snprintf(buffer,17,"%s %s",tens[dec],ones[uns]);
    return(buffer);
}

int main()
{
    int x;

    for(x=0; x<=100; x++ )
        printf("%s\n",verbal(x));

    return(0);
}

This solution is specific to values 0 through 100, as used in the main() function. I didn’t write any safety valves in the verbal() function to deal with out-of-range values.

Starting at Line 30, values 20 and greater are tested. To obtain the multiple of ten, the dec variable is assigned in this statement:

dec = (n - 20) / 10;

The first string in the tens[] array is "twenty", element zero. So the value of dec must reference this element as zero when n is equal to 20, then incremented by one for each subsequent value of 10.

Variable uns tracks what you could call the offset within each multiple of 10. Its value is set at Line 33:

uns = (n - 20) % 10 - 1;

As an example, if variable n is equal to 44, the value of dec will be 3 for string "forty" and the value of uns will be 3 for string "four". When n is evenly divisible by 10, the value of uns is calculated as negative, a condition that’s tested for at Line 35:

if( uns < 0 )
    return(tens[dec]);

At Line 38, the tens[] string and the uns[] string are thrust into a buffer to return as a single return string, dealing with the between numbers.

The full output for my solution can be viewed here.

I hope your solution worked and that you devised some type of clever mechanism to handle the redundancy in the output. That’s really the key here. In fact, if you want, you can continue to modify the program to generate output to 10,000. Doing so adds only a few more lines of code.

Leave a Reply