A Grid of Random Stars, Part VI

The program may output what I want, but the code isn’t done yet. Continuing from last week’s Lesson, I’d like the program to output a single grid showing a summary of all the rectangles found. This update requires more changes to the existing code.

My first attempt to create a single grid output resulted in a surprising reduction in the number of rectangles found. I don’t have a screenshot of the result, but the program went from finding 50+ rectangles to just a handful.

After much gnashing of teeth, I discover that mapping out rectangles as each one was found resulted in many asterisks being overwritten. Therefore, fewer asterisks remained in the grid. Not good.

To resolve this issue, I add a new array to the code: all[]. It’s a rect structure array, which stores the coordinates for each found rectangle. This data is gathered in the code’s main nested loop. When complete, the all[] array is used to plot the rectangles. At that point, it doesn’t matter if any asterisks are overwritten as their location is already recorded.

I also modified the update_grid() function to avoid overwriting as much of the grid as possible. I don’t know if this change affected the output as it’s going to be a mess anyway.

Here is the updated code:

2024_06_22-Lesson.c

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

#define ROWS 16
#define COLS ROWS*2
#define SIZE COLS*ROWS
#define PROB 5

struct rect {
    int top;
    int bottom;
    int left;
    int right;
};

void update_grid(char *g,struct rect r)
{
    int row,col;

    for( row=0; row<ROWS; row++ )
    {
        for( col=0; col<COLS; col++ )
        {
            if(
                    (row==r.top && (col>r.left && col<r.right) ) ||
                    (row==r.bottom && (col>r.left && col<r.right) )
              )
                if( *(g+row*COLS+col) == '.' )
                    *(g+row*COLS+col) = '-';
            if(
                    (col==r.left && (row>r.top && row<r.bottom) ) ||
                    (col==r.right && (row>r.top && row<r.bottom) )
                   )
                if( *(g+row*COLS+col) == '.' )
                    *(g+row*COLS+col) = '|';
        }
    }
}

int main()
{
    char *grid;
    int row,col,count,x;
    struct rect r,all[SIZE];

    /* seed the randomizer */
    srand( (unsigned)time(NULL) );

    /* allocate grid */
    grid = malloc( sizeof(char) * SIZE );
    if( grid==NULL )
    {
        fprintf(stderr,"Unable to allocate memory\n");
        exit(1);
    }

    /* fill and show the grid */
    puts("Original grid:");
    for( row=0; row<ROWS; row++ )
    {
        for( col=0; col<COLS; col++ )
        {
            if( rand() % PROB )
                putchar( *(grid+row*COLS+col) = '.');
            else
                putchar( *(grid+row*COLS+col) = '*');
        }
        putchar('\n');
    }

    count = 0;
    /* scan for two in a column */
    for( r.top=0; r.top<ROWS-1; r.top++ )
    {
        for( r.left=0; r.left<COLS; r.left++ )
        {
            /* find a star in the row */
            if( *(grid+r.top*COLS+r.left) == '*' )
            {
                /* look for a matching star in the same column */
                for( r.bottom=r.top+1; r.bottom<ROWS; r.bottom++ )
                {
                    if( *(grid+r.bottom*COLS+r.left) == '*' )
                    {
                        for( r.right=r.left+1; r.right<COLS; r.right++ )
                        {
                            if( *(grid+r.top*COLS+r.right)=='*' && *(grid+r.bottom*COLS+r.right)=='*' )
                            {
                                /* add the grid to the array */
                                all[count] = r;
                                count++;
                            }
                        }
                    }
                }
            }
        }
    }

    /* build the full grid */
    for( x=0; x<count; x++ )
        update_grid(grid,all[x]);

    /* output the final grid */
    printf("Found %d rectangles\n",count);
    for( row=0; row<ROWS; row++ )
    {
        for( col=0; col<COLS; col++ )
            putchar( *(grid+row*COLS+col) );
        putchar('\n');
    }

    return 0;
}

In the main() function, the original, pristine grid is output first. Then, in the nested loop, the call to update_grid() is replaced with:all[count] = r; The coordinates the struct rect variable r are saved to the all[] array.

After the main nested loop finishes, a for loop calls update_grid() to plot each of the rectangles found:

for( x=0; x<count; x++ )
    update_grid(grid,all[x]);

Finally, the updated grid is output, along with the count:

Original grid:
*..........*.*.*...*.**..*......
.......*..........*........**.*.
....*......*............*..***.*
.*.......***...**..**.....*.....
..**.**..*......***.*......*....
*.....*.....*....*..*......*....
................**.*..*.*.......
......*.......*..*.*....**.**...
*..............*..**............
...*....*.....*.....**...*......
..........*..*.....*..*...**....
.....*.*..*......*...........*..
..*.*........*.................*
.........*...**......*..........
...*.......................**..*
..*...*......*....*.......**..*.
Found 71 rectangles
*----------*-*-*---*-**--*......
|......*...|.|.|..*|-||--|-**-*.
|...*------*-|-|--||-||-*|-***|*
|*..|....***---**--**||-||*||.||
|.**|**--*---|-|***|*||--|-*|.||
*.||||*---|-*|-||*||*||-|||*|.||
|.|||||...|..|.|**|*-|*-*||||.||
|.||||*---|--|*|-*|*-||-**-**.||
*--------------*--**|||..||||.||
..|*|-|-*-|--|*---||**|--*|||.||
..|||||...*--*-----*--*---**|.||
..|||*|*--*--|---*|..|....|||*||
..*|*--------*----|--|-----||-|*
..||..|..*...**------*....|||.||
..|*--|-----------|--------**-|*
..*---*------*----*-------**--*.

This output could be made pretty by adding colors, which I may do in the future. But I did notice one more change that make the code easier to read: removing pointer notation. This update is presented in next week’s Lesson.

Leave a Reply