1. A block of M rows by N columns is given
2. Each item can either be a mine or not a mine
3. The location of the mines in the block is given by the character *
4. Normal/safe squares are marked by '.' (dots)
See the below table and write a program to print the number of mines adjacent to the safe blocks.
Update: This problem is from the book "Programming Challenges - The Programming Contest Training Manual - Skiena".
Example:
| input | output |
| 4 4 | Field #1: |
| *... | *100 |
| .... | 2210 |
| .*.. | 1*10 |
| .... | 1110 |
| 3 5 | Field #2: |
| **... | **100 |
| ..... | 33200 |
| .*... | 1*100 |
| 6 5 | Field #3: |
| .*.*. | 2*3*2 |
| *.*.* | *3*3* |
| ..... | 35453 |
| ***** | ***** |
| .*.*. | 3*5*3 |
| ..... | 11211 |
| 1 1 | Field #4: |
| . | 0 |
| 1 1 | Field #5: |
| * | * |
| 2 2 | Field #6: |
| *. | *2 |
| .* | 2* |
| 0 0 |
Program:
#include <stdio.h>
#include <malloc.h>
#define MINE -1
void Read_Arrays();
void FillNumbers(int * array, int rows, int cols);
void UpdateNeighbors(int *array, int row_index, int col_index, int max_row, int max_col);
void print_array(int *array, int rows, int cols);
int get_val(int *array, int row_index, int col_index, int cols);
// increment the value at the specified array location
int inc_val(int *array, int row_index, int col_index, int cols);
int main(void)
{
Read_Arrays();
}
void Read_Arrays()
{
int rows = 0;
int cols = 0;
int cur_row_index;
int *array;
char line[256];
int field_num = 0;
while(fgets(line, 256, stdin) != NULL)
{
int i=0;
if(rows == 0 && cols == 0)
{
sscanf(line, "%d %d", &rows, &cols);
array = (int *)malloc(rows*cols*sizeof(int));
if(array == NULL)
{
printf("failed to allocate memory\n");
return;
}
if(rows == 0 || cols == 0)
{
return;
}
cur_row_index = 0;
continue;
}
for(i= 0; i<cols; i++)
{
char c = line[i];
if(c == '*')
c = MINE;
else
c = 0;
*(array + (cur_row_index*cols)+i) = c;
}
//if we scanned the specified number of rows lets process the array
if(cur_row_index == rows - 1)
{
FillNumbers(array, rows, cols);
printf("Field #%d:\n", ++field_num);
print_array(array, rows, cols);
free(array);
rows = 0;
cols = 0;
}
else
{
cur_row_index++;
}
}
}
/* fill numbers in the array instead of dots */
void FillNumbers(int *array, int rows, int cols)
{
int i, j;
for(i=0; i<rows; i++)
{
for(j=0; j < cols; j++)
{
if(*(array + (i*cols) + j) == MINE)
{
UpdateNeighbors(array, i, j, rows, cols);
}
}
}
}
/* this function will increment mine count for the neighbors of the mine */
void UpdateNeighbors(int *array, int row_index, int col_index, int max_row, int max_col)
{
if(row_index-1 >= 0)
{
if(col_index - 1 >= 0)
inc_val(array, row_index - 1, col_index -1, max_col);
inc_val(array, row_index -1, col_index, max_col);
if(col_index + 1 < max_col)
inc_val(array, row_index -1, col_index + 1, max_col);
}
if(col_index - 1 >= 0)
inc_val(array, row_index, col_index - 1, max_col);
if(col_index + 1 < max_col)
inc_val(array, row_index, col_index + 1, max_col);
if(row_index + 1 < max_row)
{
if(col_index - 1 >= 0)
inc_val(array, row_index + 1, col_index -1, max_col);
inc_val(array, row_index + 1, col_index, max_col);
if(col_index + 1 < max_col)
inc_val(array, row_index + 1, col_index+1, max_col);
}
}
int get_val(int *array, int row_index, int col_index, int cols)
{
return *(array + (row_index * cols) + col_index);
}
/* we increment only if there is no mine present at the specified location */
int inc_val(int *array, int row_index, int col_index, int cols)
{
int val = get_val(array, row_index, col_index, cols);
if(val == MINE) return;
*(array + (row_index * cols) + col_index) += 1;
}
void print_array(int *array, int rows, int cols)
{
int i, j;
for(i = 0; i < rows; i++)
{
for(j = 0; j < cols; j++)
{
int val = get_val(array, i, j, cols);
if(val != MINE)
printf("%d", val);
else
printf("%c", '*');
}
printf("\n");
}
}