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.