For example
(* denotes a filled cell) 4 * * 3 * * y 2 * * 1 * * 0 * * * 0 1 2 3 4 x For the above figure blob_check(grid, 1, 3) should return a value of 5 blob_check(grid, 0, 1) should return a value of 2 blob_check(grid, 4, 4) should return a value of 0 blob_check(grid, 4, 0) should return a value of 4
For any particular cell (x, y) there are three possibilities.
In the first two cases the size of the blob containing the cell(x, y) is zero because there is no blob. For the last case however further computations will be needed and so 1 and 2 are our base cases.
We must define the size of the blob containing the filled cell (x, y) in terms of the size of one or more smaller blobs. If we mark the filled cell (x, y) empty the moment we visit it then we can redefine the problem as follows:
1 If (the cell (x, y) is EMPTY) then the count is 0 2 else if (the cell (x, y) is ZERO) then the count is 0 3 else if (the cell (x, y) is FILLED) then mark the cell (x, y) as EMPTY the count is 1 + the counts of the cell (x, y)'s eight neighbours.
Everytime the routine visits a filled cell it marks it empty BEFORE it visits its neighbours, reducing the size of the blob by one. Eventually all of the filled cells in the blob will be marked EMPTY and the routine will encounter nothing but base cases.
The sum of all the values returned from the eight recursive calls to the neighbour cells is the size of the blob containing the current cell.
A side effect of the blob_check routine is that all the elements of the blob containing the cell (x, y) are set to EMPTY. In other words the blob is erased.
If the cell visited is off the grid[][] or EMPTY, blob_check returns a 0 immediately. Otherwise the recursive step executes.
blob_check calls itself eight times, each time a different neighbour of the current cell is visited. The cells are visited in a clockwise manner starting with the neighbour above and to the left.
The routine blob_check() tests whether the cell (x, y) is on the grid before testing if it is empty. If the order were reversed then the condition ( grid[x][y] = EMPTY ) would reference an out-of-range element whenever the cell (x, y) was off the grid.
The statement grid[x][y] <- EMPTY; is used to set up conditions that will help solve a smaller version of the same problem and consequently preceeds the recursive calls.
If this statement was not executed first, then cell (x, y) would be counted more than once since it is a neighbour of each of its eight neighbours. In fact a much worse problem would occur. When each neighbour of the cell (x, y)is visited blob_check() is called again with the coordinates of the cell (x, y) as arguments. Thus if the cell (x, y) were still FILLED the recursive step would be executed erroneously and an infinite sequence of calls would be generated.
Write a routine which makes a copy of grid[][] and passes it, along with the parameters x and y, to blob_check . blob_size should return the value computed by blob_check as its own result. A call to blob_check will now not result in erasure of a blob on the original grid. This is the usual procedure to handle the aforementioned problem. Placing the copy operation at the beginning of our recursive routine would lead to the creation of a new grid on every recursive call - a totally unnecessary and very expensive waste of computing time and space.
Write a program to solve this problem recursively. In addition your program should read in the grid data from a file. The file will be structured as follows: The first line will contain two integers, the number of rows, followed by the number of columns. Subsequent lines will contain the actual data coded as 0's (empty) and 1's (full). The above data would be coded in a file as follows:
5 5 0 1 0 1 1 1 0 0 0 1 0 0 1 0 1 0 1 1 0 0 1 1 0 0 0
Note that the rows are presented from 0 to 4 in the file, rather than from 4 to 0 in the pictorial representation above.
Your program should simply output the values for each square in the grid. I will put some sample files in the course materials folder.
Put your project in the drop box with the usual naming restrictions.