I'm trying in C to write a recursive function that takes as an input an NxM matrix, and finds, checks specific cells and changes their content based on a scenario.
Original matrix
The matrix elements are:
1 2 3 4 5 6 7 8
------------------
1| 1 6 7 4 4 1 2 8
2| 1 3 6 3 3 1 3 4
3| 3 4 1 5 7 8 5 1
4| 1 7 8 6 2 6 4 4
5| 7 8 1 6 2 2 7 1
6| 3 8 4 3 1 6 8 6
7| 3 8 7 5 4 6 6 6
8| 7 2 2 1 7 4 6 8
Based on a matrix like the above, a user gives the location of a specific cell, e.g. position (5,6) for the integer 2. I want the recursive function to check the cells in the four directions, up, down, left, right and if it finds the same integer to change them to 0s. This will continue for all the "neighborhood" cells. In this example all twos at positions (5,6), (5,5) and (4,5) will change to 0s.
Another example:
user gives location i.e. position (8,7) for the integer 6. The recursive function has to find and change all 6s at the positions (8,7), (7,7), (7,8), (7,6), (6,6), (6,8) and set them to 0s.
void destroy(int (*arr), int rows, int cols,int search,int rowin, int colin) //rows: total rows of matrxi, cols:total cols of matrix, rowin and colin are the x,y co ordinates of the cell that the user wants to destroy and search has the int i.e 6 ..
{
int i, j;
printf("\n");
printf("\n");
int count = 0,temp = 0;
for (j = 0; j < cols; j++) {
for (i = 0; i < rows; i++) {
if (*(arr + i*cols + j)== search) {
if (*(arr + (i-1)*cols + j) == search){//check neighborhood cell
count++; //counter to know how many similar neighborhood integers have been found
(*(arr + i*cols + j)= 0);
*(arr + (i-1)*cols + j) = 0;
destroy(int (*arr), int rows, int cols,int search, j, i) //call recursive function to check the neighborhood cells of the new position i,j
}
}
}
}
}
You don't need for loops but four recursive calls to check each neighborhood.
void destroy(int *arr, int rows, int cols,int search,int rowin, int colin)
{
if (rowin>=rows || colin >= cols || rowin < 0 || colin <0)
return; //base condition
if (arr[rowin*cols+colin] == search)
{
arr[rowin*cols+colin] = 0;
destroy(arr, rows, cols, search, rowin+1, colin);
destroy(arr, rows, cols, search, rowin, colin+1);
destroy(arr, rows, cols, search, rowin-1, colin);
destroy(arr, rows, cols, search, rowin, colin-1);
}
}
Notice that in C an array index starts from zero (not one).
Here is an example that uses a matrix (aka array of array).
#include <stdio.h>
void destroy(int value, int r, int c, int r_size, int c_size, int arr[][r_size])
{
if (value != arr[r][c]) return; // Nothing to do
arr[r][c] = 0;
if (r+1 < r_size) destroy(value, r+1, c, r_size, c_size, arr); // DOWN
if (r-1 >= 0) destroy(value, r-1, c, r_size, c_size, arr); // UP
if (c+1 < c_size) destroy(value, r, c+1, r_size, c_size, arr); // RIGHT
if (c-1 >= 0) destroy(value, r, c-1, r_size, c_size, arr); // LEFT
}
void pm(int r_size, int c_size, int arr[r_size][r_size])
{
printf("-------------------------------------------\n");
for (int r=0; r < r_size; ++r)
{
for (int c=0; c < c_size; ++c)
{
printf("%d ", arr[r][c]);
}
printf("\n");
}
}
#define MSIZE 8
int main(void) {
int arr[MSIZE][MSIZE] =
{
{1, 6, 7, 4, 4, 1, 2, 8},
{1, 3, 6, 3, 3, 1, 3, 4},
{3, 4, 1, 5, 7, 8, 5, 1},
{1, 7, 8, 6, 2, 6, 4, 4},
{7, 8, 1, 6, 2, 2, 7, 1},
{3, 8, 4, 3, 1, 6, 8, 6},
{3, 8, 7, 5, 4, 6, 6, 6},
{7, 2, 2, 1, 7, 4, 6, 8}
};
pm(MSIZE, MSIZE, arr);
destroy(arr[7][6], 7, 6, MSIZE, MSIZE, arr);
pm(MSIZE, MSIZE, arr);
return 0;
}
Output:
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 6 8 6
3 8 7 5 4 6 6 6
7 2 2 1 7 4 6 8
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 0 8 0
3 8 7 5 4 0 0 0
7 2 2 1 7 4 0 8
Version 2
This version a little different because it only changes elements if at least one neighbor is found. Also it counts the number of changes.
#include <stdio.h>
#include <stdlib.h>
int destroy_rec(int value, int r, int c, int r_size, int c_size, int arr[][r_size])
{
if (value != arr[r][c]) return 0; // Nothing to do
int changed = 1;
arr[r][c] = 0;
if (r+1 < r_size) changed += destroy_rec(value, r+1, c, r_size, c_size, arr); // DOWN
if (r-1 >= 0) changed += destroy_rec(value, r-1, c, r_size, c_size, arr); // UP
if (c+1 < c_size) changed += destroy_rec(value, r, c+1, r_size, c_size, arr); // RIGHT
if (c-1 >= 0) changed += destroy_rec(value, r, c-1, r_size, c_size, arr); // LEFT
return changed;
}
int destroy(int r, int c, int r_size, int c_size, int arr[][r_size])
{
if (r+1 < r_size && arr[r+1][c] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
if (r-1 >= 0 && arr[r-1][c] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
if (c+1 < c_size && arr[r][c+1] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
if (c-1 >= 0 && arr[r][c-1] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
return 0;
}
void pm(int r_size, int c_size, int arr[r_size][r_size])
{
printf("-------------------------------------------\n");
for (int r=0; r < r_size; ++r)
{
for (int c=0; c < c_size; ++c)
{
printf("%d ", arr[r][c]);
}
printf("\n");
}
printf("-------------------------------------------\n");
}
#define MSIZE 8
int main(void) {
int arr[MSIZE][MSIZE] =
{
{1, 6, 7, 4, 4, 1, 2, 8},
{1, 3, 6, 3, 3, 1, 3, 4},
{3, 4, 1, 5, 7, 8, 5, 1},
{1, 7, 8, 6, 2, 6, 4, 4},
{7, 8, 1, 6, 2, 2, 7, 1},
{3, 8, 4, 3, 1, 6, 8, 6},
{3, 8, 7, 5, 4, 6, 6, 6},
{7, 2, 2, 1, 7, 4, 6, 8}
};
pm(MSIZE, MSIZE, arr);
int changed = destroy(7, 6, MSIZE, MSIZE, arr);
printf("%d cells changed\n", changed);
pm(MSIZE, MSIZE, arr);
int (*dyn_arr)[MSIZE] = malloc(MSIZE * sizeof *dyn_arr);
return 0;
}
Output:
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 6 8 6
3 8 7 5 4 6 6 6
7 2 2 1 7 4 6 8
-------------------------------------------
6 cells changed
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 0 8 0
3 8 7 5 4 0 0 0
7 2 2 1 7 4 0 8
-------------------------------------------
I don't know what you want to achieve with this because in your code you're already traversing through whole array and after checking one element you want to traverse again.
In my point of view you don't need another iteration to remove the elements. You can perform this in a single iteration.
If the element you're searching exists then remove the neighbor elements
(i,j => (i-1,j : i+1,j : i,j-1 : i,j+1))
In this way you might need to put some checks on index value to avoid undefined behaviour.
Is am trying to figure out how to generate this sequence of numbers in C.
0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 8, 9 …
The sequence is generated by forming a triangle of numbers as shown below:
0
1 2
3 4 5
6 7 8 9 ...
Next two numbers in series are located as follows:
Next number is located directly below
Next to next is located one place to the right.
0
|\
1 2
Series -> 0, 1, 2
0
|\
1 2
|\|\
3 4 5
Series -> 0, 1, 2, 3, 4, 4, 5, ........
How can I traverse this number triangle to get this sequence in C?
It means that
0 is replaced with 1 and 2
1 is replaced with 3 and 4
2 is replaced with 4 and 5
0
|\
1 2
|\|\
3 4 5
|\|\|\
6 7 8 9
Series -> 0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 7, 8, 8, 9 ........
It means that
I. Solving 0
0 leads to 1 and 2
0 -> 1 - 2
0 1 2
II. Solving 1 and 2
1 leads to 3 and 4
1 -> 3 - 4
0 1 2 3 4
2 leads to 4 and 5
2 -> 4 - 5
0 1 2 3 4 4 5
III. Solving 3, 4, 4, 5
3 leads to 6 and 7
3 -> 6 - 7
0 1 2 3 4 4 5 6 7
4 leads to 7 and 8
4 -> 7 - 8
0 1 2 3 4 4 5 6 7 7 8
4 leads to 7 and 8
4 -> 7 - 8
0 1 2 3 4 4 5 6 7 7 8 7 8
5 leads to 8 and 9
5 -> 8 - 9
0 1 2 3 4 4 5 6 7 7 8 7 8 8 9
My apologies for not explaining properly. I hope I explain it this time.
I assume (based on the description) your sequence should be indeed
0
1 2
3 4 4 5
6 7 7 8 8 9
10 11 11 12 12 13 13 14
etc.
You can work with it with the code like that:
int nextRowStart = 0;
int nextRowSize = 1;
for (int curr = 0; /*put some ending condition here*/; curr++)
{
yield(curr)
if (curr != nextRowStart - 1 && curr != nextRowStart)
yield(curr);
if (curr == nextRowStart)
{
nextRowStart += nextRowSize;
nextRowSize++;
}
}
void yield(int x)
{
printf("%d ", x);
}
With the changed question, the new one can be done recursively
This is the solution in C#:
IEnumerable<int> Generate(int level)
{
if (level == 0)
{
yield return 0;
yield break;
}
int diff = level;
foreach (int n in Generate(level - 1))
{
yield return n + diff;
yield return n + diff + 1;
}
}
var result = Enumerable.Range(0, maxLevel).SelectMany(Generate);
It would take some time to translate it into C...
C solution:
void Generate(int level, int* resultsize, int** result)
{
if (level == 0)
{
*result = (int*)malloc(sizeof(int));
(*result)[0] = 0;
*resultsize = 1;
}
else
{
int recResultSize;
int* recResult;
Generate(level - 1, &recResultSize, &recResult);
*resultsize = recResultSize * 2;
*result = (int*)malloc(*resultsize * sizeof(int));
for (int i = 0; i < recResultSize; i++)
{
(*result)[2*i] = recResult[i] + level;
(*result)[2*i + 1] = recResult[i] + level + 1;
}
free(recResult);
}
}
This is the code which gives the exact result and solves the problem. I came at this result just when #Lundin asked me to post my code , I tried again and I was successful. Thanks guys.
#include<stdio.h>
int in;
int main(){
int ik, it, icount = 0, ih, temp, ig = 1;
int aisum[100];
aisum[0] = 0;
scanf("%d",&in);
printf("0\n");
it = 1;ih = 0;temp = 2;
for(icount = 0,ig = 1; icount <= in; icount++){
for(ik = 0; ik<2; ik++){
aisum[ig] = aisum[icount] + it + ik ;
printf("%d ",aisum[ig]);
ig++;
}
if(aisum[icount] == ih){
printf("\n");
it++;
ih += temp;
temp++;
}
}
return 0;
}
/*Input the number of elements to be processed*/
/*icount will account for new elements to be formed like if we look
at pascal triangle
0 will form 1 and 2
1 will form 3 and 4
*/
/*ig will account for array indices*/
/*it will account for the periodic addition */
/*ih checks for the codnition for it to increement
0
1 2
3 4 5
it will be increemented at 0, 2, 5 ...
*/
The simplest solution I can give from below triangle to required order is...
0
1 2
3 4 5
6 7 8 9
printing start and end nodes of each line and printing center elements 2 times each...
for each line start will be equals to previous end+1...
end will be equal to end+1+count...
count will be incremented by 1 for each line...
CPP Program:
#include<iostream>
using namespace std;
int main()
{
int start=1,end=2,count=1;
cout<<0<<" ";
while(count<5)
{
cout<<start<<" ";
for(int i=start+1;i<end;i++)
{
cout<<i<<" "<<i<<" ";
}
cout<<end<<" ";
count++;
start=end+1;
end=start+count;
}
return 0;
}