CS 1723, Data Structures Assignment 6, Recursive Boundary Recognition Due April ??, 1997 The assignment: You are to carry out a simple task from image processing: Given a 2- dimensional "image" consisting of a square array of Ascii characters, and given a "boundary" of some region in the square, identify the entire region. The boundary will be made up from a specific character, say '*'. For example, in the picture below, the boundary divides the square into six regions. One region has lower-case letters inside it, the second has upper-case letters inside it, and the remaining four smaller regions have digits inside them. | 0 1 2 3 4 5 6 7 8 9 | --+---------------------+ 0 | a b c * A B C D E F | 1 | d e f g * * * G H I | 2 | * h i j k l m * J K | 3 | 1 * n o * * p q * L | 4 | 2 * r * M N * s * O | 5 | * * t u * P Q * R S | 6 | * v w x * T U V W * | 7 | 1 * y z * * X Y Z * | 8 | 2 3 * * * * * * * 1 | 9 | 4 * 1 2 * 2 3 4 5 6 | --+---------------------+ You are to write three C functions with prototypes void fill1(int row, int col, char bdry); void fill2(int row, int col, char bdry); void fill3(int row, int col, char bdry); each of which will fill the region containing the point (row, col) with the boundary character. For example, a call fill1(0, 0, '*'); should result in the following changes to the array contents: | 0 1 2 3 4 5 6 7 8 9 | --+---------------------+ 0 | * * * * A B C D E F | 1 | * * * * * * * G H I | 2 | * * * * * * * * J K | 3 | 1 * * * * * * * * L | 4 | 2 * * * M N * * * O | 5 | * * * * * P Q * R S | 6 | * * * * * T U V W * | 7 | 1 * * * * * X Y Z * | 8 | 2 3 * * * * * * * 1 | 9 | 4 * 1 2 * 2 3 4 5 6 | --+---------------------+ Notice that only the region containing (0,0) has been filled with the boundary character. The function fill1() must be implemented as a recursive function which examines the character at position (row,col). If this character is not the boundary character, then the function changes it to the boundary character, and then calls itself with the four character positions above, below, to the left, and to the right as the input positions. (There are at most four such positions, since you must stay within the array bounds. If the border position is outside the array, you don't call. If the character at position (row,col) is the boundary character, fill1() does nothing.) The function fill2() must work with a stack of array positions (pairs of integers). Some initial position is pushed. fill2() pops the stack and examines the specified position. If the position is not the boundary character, fill2() should change it to the boundary character and then push the four array positions above, below, to the left, and to the right of the position that was popped (unless one of these is outside the array). fill2() repeats this in a loop as long as the stack is non-empty. The function fill3() must be the same as fill2(), except that it uses a queue for array positions, rather than a stack. Notice that fill2() and fill3() will not use recursion. What to turn in: Your program should show the result of running each of fill1(), fill2(), and fill3() in turn with (0,0) as the initial position, and then the result of each of the three with (0,9) as the initial position. (Above, (0,9) holds the letter 'F'.) You should just read a copy of the array one time, and save the copy for use by the second and third functions. In order to get more interesting output, each of the fill's should, just before changing a character to the boundary character, print the character (with no newline). Then print the resulting array. Thus we expect to see printed a list of the 26 letters (in some order on a single line) for each of the fill's. (Lower-case letters for the first run and upper-case letters for the second run.) The output might look as follows. (This gives the order in which the positions were replaced by a '*'.) adebcfinrtwyzxuvojgklmpqsh You may use any of the old stack or queue code (either based on arrays or linked lists) that you wish, though of course it will have to be adapted to provide a stack or queue of pairs of integers. You must use a struct for the pair of integers, and each stack and queue must be a separate file with a separate header file. The initial array will be in the directory ~wagner/pub/CS1723, under the name "region.text". runner% cat region.text abc*ABCDEF defg***GHI *hijklm*JK 1*no**pq*L 2*r*MN*s*O **tu*PQ*RS *vwx*TUVW* 1*yz**XYZ* 23*******1 4*12*23456 Using an array of pointers to functions: Since we have to call 3 functions twice each, it will be convenient to use an array holding the three functions so that we can make use of them. For this purpose, you should use the following code in order to exercise your three functions: #define MAXA 10 char grid[MAXA][MAXA]; char gridsave[MAXA][MAXA]; void fill1(int row, int col, char bdry); void fill2(int row, int col, char bdry); void fill3(int row, int col, char bdry); void exec_fill( void (* )(int, int, char), char *); void readarray(char [MAXA][MAXA]); void printarray(char [MAXA][MAXA]); void copyarray(char [MAXA][MAXA], char [MAXA][MAXA]); struct { void (*fill)(int, int, char); char *name; } f[] = { {fill1, "fill1"}, {fill2, "fill2"}, {fill3, "fill3"} }; main() { int i; readarray(gridsave); printarray(gridsave); for (i = 0; i < 3; i++) exec_fill(f[i].fill, f[i].name); return 0; } void exec_fill(void (*fill)(int, int, char), char *name) { copyarray(grid, gridsave); printf("*** Fill with %s, from (0,0)\n", name); (*fill)(0, 0, '*'); printf("\n\n"); printarray(grid); copyarray(grid, gridsave); printf("*** Fill with %s, from (0,9)\n", name); (*fill)(0, 9, '*'); printf("\n\n"); printarray(grid); }