Sorted List Presentation, Part II

It’s easy to code single-column list output. It takes a bit more programming skill to present the list in columns. To sort the list by columns is the most difficult. Like many programming tasks, it’s one of those things that once you figure it out, you just keep stealing your own code to do it again and again.

Or, as is the case these days, programmers look to github to purloin tricks they don’t have the patience to concoct themselves. Anyway . . .

I hope it’s your desire to be a coder and not a mere programmer. Sure, others have invented the wheel before you, but to hone your skills, I recommend figuring out things on your own. A good example is you to take list output like this:

 1	 2	 3	 4	 5
 6	 7	 8	 9	10
11	12	13	14	15
16	17	18	19	20
21	22	23	24	25
26	27	28	29	30

And instead output this:

 1	 7	13	19	25		
 2	 8	14	20	26		
 3	 9	15	21	27		
 4	10	16	22	28		
 5	11	17	23	29		
 6	12	18	24	30

If you had cursor control, you could write code that marches output down each row, then hops to the top of the next column to repeat until done. You do not have cursor control, however, so you must output the list by rows, sorted by columns.

Because the data set is constant in the sample program, you know that you have 30 items. The existing code sorts that list into six rows of five columns: 30, 6, 5. When I struggled to solve this problem, I knew all these constants and I scrutinized the second list (above) to divinate a solution. Here’s my observation:

Each column element is n+rows greater than the element to the left. If you count the column position, the equation is:

rows * column_position+n

For the first row, n is 1. At row-column 0,0, the equation is 6 * 0 + 1 = 1. At position 0,1 you get 6 * 1 + 1 = 7, then 6 * 2 + 1 = 13, 6 * 3 + 1 = 19, and so on.

For the second row, first column you get 6 * 0 + 2 = 2, 6 * 1 + 2 = 8, and so on.

For the third row, 6 * 0 + 3 = 3, 6 * 1 + 3 = 9, and you get the idea.

One you have that equation, you can plug it into nested for loops to plow through the rows and columns:

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

#define ITEMS 30
#define ROWS 6
#define COLUMNS 5

int compare(const void *a, const void *b);

int main()
{
    char *fruit[] = {
        "apple", "orange", "blueberry", "date", "melon",
        "grape", "peach", "mango", "watermelon", "pear",
        "olive", "plum", "nectarine", "kiwi", "loquat",
        "honeydew", "lime", "grapefruit", "cherry",
        "avocado", "tomato", "banana", "cantaloupe",
        "huckleberry", "kumquat", "tangerine", "fig",
        "raspberry", "papaya", "lychee"
    };
    int r,c;

/* quicksort the list */
    qsort(fruit,ITEMS,sizeof(char *),compare);

/* display sorted strings */
    for(r=0;r<ROWS;r++)
    {
        for(c=0;c<COLUMNS;c++)
            printf("%-12s",fruit[ROWS*c+r]);
        putchar('\n');
    }

    return(0);
}

/* compare routine for quicksort */
int compare(const void *a, const void *b)
{
    const char **pa, **pb;

    pa = (const char **)a;
    pb = (const char **)b;
    return( strcmp(*pa,*pb) );
}

The code defines the constants I know: ITEMS, ROWS, and COLUMNS. These values for ROWS and COLUMNS are used in the nested for loops at Lines 28 and 30. The rows*column_position+n algorithm appears in the printf() statement at Line 31 to determine which array element is displayed:

ROWS*c+r

c is the column number. r is the row number, 0 through ROWS (6). The result is output sorted by columns:

apple       date        kiwi        melon       pear        
avocado     fig         kumquat     nectarine   plum        
banana      grape       lime        olive       raspberry   
blueberry   grapefruit  loquat      orange      tangerine   
cantaloupe  honeydew    lychee      papaya      tomato      
cherry      huckleberry mango       peach       watermelon

This is exactly the output the Boss wants. But . . . (and if you’re a programmer, you know what’s coming next) . . . the Boss wants you to add five fruits to the list: guava, persimmon, coconut, cranberry, and chestnut.

You can continue to use constants (bad) or (better) accept that you need variables in the code instead. I begin this process in next week’s Lesson.

Leave a Reply