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.