Find number of paths in a 2d binary array (C) - c

I have been asked this question during an interview, and have been struggling to find an elegant solution (in C), Problem statement:
You are given a two-dimensional array with M rows and N columns.
You are initially positioned at (0,0) which is the top-left cell in
the array.
You are allowed to move either right or downwards.
The array is filled with 1′s and 0′s. A 1 indicates that you can move
through that cell, a 0 indicates that you cannot move through the
cell.
Write a function in C ‘numberOfPaths’ which takes in the above two dimensional array, return the number of valid paths from the top-left cell to the bottom-right cell (i.e. [0,0] to [M-1,N-1]).
Edit: forgot to mention that the requirement is for a recursive solution
help would be greatly appreciated!
Thanks

If you are looking for a recursive solution you can use DFS.
DFS (array, x, y)
{
if (array [x][y]==0 || x>M || y>N){
return;
}
if (x==M && y==N){
count++;
return;
}
DFS (array, x, y+1);
DFS (array, x+1, y);
}

The number of paths to a given point is just the number of paths to the point above, plus the number of paths to the point to the left. So, the pseudo-code would roughly be:
num_paths[0][0] = 1;
for (x = 0; x < M; ++x)
for (y = 0; y < N; ++y)
if (!allowed_through[x][y])
num_paths[x][y] = 0;
else
num_paths[x][y] = num_paths[x-1][y] + num_paths[x][y-1];
You need special cases for x=0 and y=0, but otherwise, I think that should do.

#include <stdio.h>
int count=0;
int maxrows = 10;
int maxcols = 10;
int M, N;
void DFS (int array[][10], int x, int y)
{
int r, c;
/* process element at input row and column */
if (array [x][y]==0 || x>M || y>N){
/* no path forward; return */
return;
}
if (x==M-1 && y==N-1){
/* found path; increment count */
count++;
return;
}
/* recurse: to matrix starting from same row, next column */
r = x;
c = y +1;
if (c < N-1) {
DFS (array, r,c);
} else {
/* if last column - check to see */
/* if rest of rows in last column allow for a path */
int tr = r;
while ( tr <= M-1) {
if (array[tr][c] == 1) {
tr++;
}
else {
return;
}
}
/* reached last node - path exists! */
count++;
}
/* recurse: to matrix starting from next row, same column */
r = x+1;
c = y;
if (r < M-1) {
DFS (array, r,c);
} else {
/* if last row - check to see */
/* if rest of columns in last row allow for a path */
int tc = c;
while ( tc <= N-1) {
if (array[r][tc] == 1) {
tc++;
} else {
return;
}
}
/* reached last node - path exists! */
count++;
}
}
int main () {
int i, j;
scanf("%d %d",&M,&N);
int a[10][10] = {};
int row, col;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
scanf("%d", &a[i][j]);
if ((M > maxrows) || (N > maxcols)) {
printf("max of 10 rows and 10 cols allowed for input\n");
return (-1);
};
/* print input matrix */
for(row=0;row<M;row++) {
for(col=0;col<N;col++){
printf("%d ",a[row][col]);
}
printf(" EOR\n");
}
DFS(a,0,0);
printf("number of paths is %d\n", count);
return 0;
}

Try this function its a preliminary step before printing all the paths.
If the size of the vector Out is 0 then the # of paths are 0, but if size(Out) > 0 then the size of vector Nodes + 1 are the total number of paths from top left to bottom right.
#include <iostream>
#include <vector>
using namespace std;
typedef vector<pair<int,int> > vPii;
bool pathTL2BR( int Arr2D[][4], vPii &Out, vPii &Nodes,
int _x,int _y, int _M, int _N)
{
bool out1 = false;
bool out2 = false;
if( Arr2D[_x][_y] == 1 )
{
if( _y+1 < _N )
out1 = pathTL2BR( Arr2D, Out, Nodes, _x, _y+1, _M, _N);
if( _x+1 < _M )
out2 = pathTL2BR( Arr2D, Out, Nodes, _x+1, _y, _M, _N);
if( (out1 || out2) ||
( (_x == (_M-1)) && (_y == (_N-1)) ) )
{
if(out1 && out2)
Nodes.push_back( make_pair(_x,_y ) );
Out.push_back( make_pair(_x,_y ) );
return true;
}
else
return false;
}
else
return false;
}
// Driver program to test above function
int main()
{
int Arr2D[][4] = {
{1,1,1,1},
{0,1,0,1},
{0,1,0,1},
{0,1,0,1}
};
vPii Out;
vPii Nodes;
vector<vPii> Output;
pathTL2BR( Arr2D, Out, Nodes, 0, 0, 4, 4);
return 0;
}

This is a python solution, I have put explanations in the comments.
def find_num_paths(arr_2D, i, j):
# i,j is the start point and you have to travel all the way back to 0,0
if i == j and i == 0:
return 1 # you have reached the start point
if i < 0 or j < 0 or arr_2D[i][j] == 0: # out of range or no path from that point
return 0
if arr_2D[i][j] == 1:
return find_num_paths(arr_2D, i, j-1) + find_num_paths(arr_2D, i-1, j) + find_num_paths(arr_2D, i-1, j-1) # you could go one step above, to the left or diagonally up.

Related

Cycle through an array in either direction based on a bool

I'm looking for a method of looping through some array in either direction based on some passed bool value, with the same functionality as:
void Transfer(bool *_payload, int _size, bool _isLSB)
{
if (_isLSB)
{
for (int i = _size - 1; i >= 0; i--)
{
digitalWrite(dataPin, _payload[i]);
}
}
else
{
for (int i = 0; i < _size; i++)
{
digitalWrite(dataPin, _payload[i]);
}
}
}
or
void Transfer(bool *_payload, int _size, bool _isLSB)
{
int _index = 0;
if (_isLSB) _index = _size - 1;
for (;;)
{
printf("%d",_payload[_index]);
if (_isLSB) _index--;
else _index++;
if (_isLSB && _index < 0) break;
if (!_isLSB && _index >= _size) break;
}
}
Other than creating a method that reverses the array, is there a nice simplification of this?
You can define the starting and ending point and the increment conditionally:
void Transfer(bool *_payload, int _size, bool _isLSB)
{
int increment = _isLSB ? -1 : 1;
int i = _isLSB ? _size : -1; // one before the area to scan
int end = _isLSB ? -1 : _size; // one past the area
while ((i += increment) != end) // incr/decr before testing
{
digitalWrite(dataPin, _payload[i]);
}
}
We do not know in advance which way the index will be changing (incrementing or decrementing), so we can't use less-than or greater-than in the loop condition. And after processing the last item the index will be modified once more, hence the stopping point is one past the area being processed.
Similarly we need the starting point one position before the scanned area, so that after incrementing (or decrementing) the index we process the valid, first item.
You can calculate the direction and the start/end position for the for loop depending on _isLSB
void Transfer(bool* _payload, int _size, bool _isLSB) {
int dir;
int start;
int end;
if(_isLSB) {
dir = -1;
start = _size-1;
end = -1;
}else {
dir = 1;
start = 0;
end = _size;
}
for(int i = start; i != end; i+=dir) {
digitalWrite(dataPin, _payload[i]);
}
}
What you could do for example, since in C true and false are expanded to integer values in reality, is to use said integer value for calculations.
In the following example I will extract the main problem from your question which is: Looping over a size in a direction depending on a boolean value
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
int main()
{
int size = 5;
bool condition = false;
// Option #1
printf("Option #1\n");
for (int i = (size - 1) * condition; (i >= 0 && condition) || (i < size && !condition); i += 1 * pow(-1, condition))
{
printf("%d", i);
}
// Option #2
printf("\nOption #2\n");
int i = (size - 1) * condition;
for (;;)
{
printf("%d", i);
i += 1 * pow(-1, condition);
if ((i < 0 && condition) || (i >= size && !condition))
break;
}
return 0;
}
With the main function giving the following output for condition = true
Option #1
01234
Option #2
01234
And the following output for condition = false
Option #1
43210
Option #2
43210

How do I change the binary search function to intake the compare?

I am having trouble with the logic of combining these two stipulations in my assignment. How do I change the below binary search function to intake the compareTo the coordinate structures. I wrote it wrong the first time because I used the original string locations. I also dont understand how the compareTo function is suppose to keep track of the length away from the target. Which is confusing to me because the way it reads below for the compareTo function says the opposite to me and asking me to compare individual x and y coordinates. how am I suppose to do that if i am just using the pointers? Am i just passing coordinates *ptrPt1 into the binary search? Number 3 is the most confusing mess of words.
Context for the function relationship:
You must write a function compareTo which takes in two pointers, ptrPt1 and ptrPt2, to
coordinate structs and returns a negative integer if the point pointed to by ptrPt1 is closer to you
than the point pointed to by ptrPt2, 0 if the two locations pointed to by both are identical locations,
and a positive integer if the point pointed to by ptrPt1 is farther from you than the point pointed to
by ptrPt2. Exceptions to this will be when the two pointers are pointing to points that are the same
distance from you, but are distinct points. In these cases, if ptrPt1's x coordinate is lower than
ptrPt2's x coordinate, a negative integer must be returned. Alternatively, if ptrPt1's x coordinate is
greater than ptrPt2's x coordinate a positive integer must be returned. Finally, if the x coordinate
of both points is the same, if ptrPt1's y coordinate is lower than ptrPt2's y coordinate, a negative
integer must be returned. If ptrPt1's y coordinate is greater than ptrPt2's y coordinate, a positive
integer must be returned.
Since your location must be used for sorting, please make the variable that stores your x and y
coordinates global. Your program should have no other global variables.
A Binary Search function must be used when answering queries.
int binarysearch(int searchval, int* array, int length) {
int low = 0, high = length-1;
// Search while there is a valid search space.
while (low <= high) {
int mid = (low+high)/2;
// Value is too small.
if (searchval < array[mid])
high = mid-1;
// too big.
else if (searchval > array[mid])
low = mid+1;
// found it!
else
return 1;
}
// Never found it.
return 0;
}
int
compareTo(coordinates *ptrPt1, coordinates *ptrPt2) {
if (ptrPt1 > ptrPt2)
return -1;
if(ptrPt1 == ptrPt2)
return 0;
if(ptrPt1 < ptrPt2)
return 1;
}
Your compareTo needs to be refactored.
Comparing the addresses of the structs [vs. the X/Y coordinates within them] is incorrect.
For compareTo, it must first compute the distance from an arbitrary reference point (e.g.) self for each of the two points passed as arguments. Per the problem definition, self can [and should] be a [the only] global.
It gets the distance to self for each of the two [argument] points. It chooses the closer of these two points [if they are different].
If the two points are the same distance from the self point, it first chooses the one with the lower X coordinate value. If the X coordinates are the same for the two points, it chooses the one that has the lower of the two Y values.
Thus, it's a three step process.
Your binarysearch needs to be refactored. Upon mismatch/failure, it returns 0. But, zero is a valid index/value for a match. So, it needs to return -1 on failure.
There are some issues with the problem definition.
Issue (1):
It's not clear [to me] what "rank" is supposed to be. The only thing that makes sense is that "rank" is the index into the list that is sorted by compareTo.
Issue (2):
It's not clear what "distance" means. It could be (e.g.):
sqrt((p1->x - p2->x)**2 + (p1->y - p2->y)**2)
But, that uses floating point, and it may be overkill for this problem.
Another "distance" is the manhattan distance which is just the sum of the absolute differences of the X and Y values of the two coordinates:
abs(p1->x - p2->x) + abs(p1->y - p2->y)
Issue (3):
I think that two sorted lists are required.
One sorted by compareTo. Another sorted just by X/Y coordinates.
This is because it is required to use a binary search when matching a search coordinate. Because the search coordinate does not know the rank, it can't use the compareTo list and must use the X/Y list.
There are two possible approaches.
This can be achieved by using two lists that are either pointers or indices into the person list. The binarysearch should be modified to accept an array of indices/pointers.
Or, it can be achieved by sorting the person list by compareTo, recording the rank in the coordinate struct and then resorting the list by X/Y coordinates. The binarysearch should be modified to accept an array of coordinates.
I've chosen to use the latter approach.
And, I've added some test code to generate a randomized input file, if desired.
I've just implemented a simple insertion sort [algorithm is a cut-n-paste from the wikipedia entry for insertion sort]. So, you'll still have to code up the combined merge/insertion sort logic.
Spoiler Alert: Below is the complete/refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <time.h>
typedef struct {
int x;
int y;
int rank;
} coord_t;
// maximum coordinate
#ifndef COORDMAX
#define COORDMAX 10000
#endif
// max # of [infected] people
#ifndef PERSONMAX
#define PERSONMAX 106
#endif
#define SEARCHMAX (2 * (PERSONMAX - 1)) // max # of search coordinates
#define THRESHMAX 30 // maximum threshold
coord_t self; // coordinates of tracer
typedef int (*cmpfnc_p)(const coord_t *,const coord_t *);
int opt_d; // 1=debug
int opt_f; // distance mode (0=manhattan, 1=sqrt)
unsigned int opt_R; // random fill
void gentest(FILE *fi);
// disti -- get distance from given coordinate to self (manhattan distance)
int
disti(const coord_t *pt)
{
int dif;
int tot = 0;
dif = pt->x - self.x;
if (dif < 0)
dif = -dif;
tot += dif;
dif = pt->y - self.y;
if (dif < 0)
dif = -dif;
tot += dif;
return tot;
}
// distf -- get distance from given coordinate to self (floating pt distance)
int
distf(const coord_t *pt)
{
double dif;
double tot = 0;
int rtn;
dif = pt->x - self.x;
dif *= dif;
tot += dif;
dif = pt->y - self.y;
dif *= dif;
tot += dif;
tot = sqrt(tot);
// scale result
// FIXME -- this is untested and may not be necessary
tot *= INT_MAX;
tot /= COORDMAX;
rtn = round(tot);
return rtn;
}
// dist -- get distance from given coordinate to self
int
dist(const coord_t *pt)
{
int tot;
if (opt_f)
tot = distf(pt);
else
tot = disti(pt);
return tot;
}
// compareAbs -- compare two coordinates for lowest X/Y values
int
compareAbs(const coord_t *p1,const coord_t *p2)
{
int cmp;
do {
// use lower X coordinate
cmp = p1->x - p2->x;
if (cmp)
break;
// use lower Y coordinate
cmp = p1->y - p2->y;
if (cmp)
break;
} while (0);
return cmp;
}
// compareTo -- compare two coordinates for distance from self and then position
int
compareTo(const coord_t *p1,const coord_t *p2)
{
int cmp;
do {
// compare distance to self
cmp = dist(p1) - dist(p2);
if (cmp)
break;
// compare against absolute coordinates
cmp = compareAbs(p1,p2);
} while (0);
return cmp;
}
// sortswap -- swap array elements
void
sortswap(coord_t *p1,coord_t *p2)
{
coord_t tmp;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
// sortinsert -- insertion sort
void
sortinsert(coord_t *list,int count,cmpfnc_p cmp)
{
for (int i = 1; i < count; ++i) {
for (int j = i; j > 0; --j) {
if (cmp(&list[j - 1],&list[j]) <= 0)
break;
sortswap(&list[j - 1],&list[j]);
}
}
}
// sortany -- outer sort routine
void
sortany(coord_t *list,int count,int threshold,cmpfnc_p cmp)
{
// TODO: do mergesort
if (count < threshold) {
}
// finish with insertion sort
sortinsert(list,count,cmp);
}
// binarysearch -- perform binary search on coordinate list
int
binarysearch(const coord_t *search,const coord_t *array,int length,
cmpfnc_p cmpfnc)
{
int low = 0;
int high = length - 1;
int match = -1;
// Search while there is a valid search space.
while (low <= high) {
int mid = (low + high) / 2;
int cmp = cmpfnc(search,&array[mid]);
// found it
if (cmp == 0) {
match = mid;
break;
}
// Value is too small.
if (cmp < 0)
high = mid - 1;
// too big.
else
low = mid + 1;
}
return match;
}
// main -- main program
int
main(int argc,char **argv)
{
const char *file = NULL;
char *cp;
FILE *fi;
int person_count;
int search_count;
int threshold;
coord_t *pt;
coord_t *person_list;
coord_t *search_list;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'd':
opt_d = ! opt_d;
break;
case 'f':
opt_f = ! opt_f;
break;
case 'R':
cp += 2;
opt_R = (*cp != 0) ? atoi(cp) : time(NULL);
printf("R=%u\n",opt_R);
srand(opt_R);
break;
}
}
// get/open input file
do {
fi = stdin;
if (argc <= 0) {
if (opt_R)
fi = stdout;
else
fi = stdin;
break;
}
file = *argv;
fi = fopen(file,opt_R ? "w" : "r");
if (fi == NULL) {
perror(file);
exit(1);
}
} while (0);
// generate test data
if (opt_R) {
gentest(fi);
fclose(fi);
exit(0);
}
fscanf(fi,"%d %d %d %d %d",
&self.x,&self.y,&person_count,&search_count,&threshold);
person_list = calloc(person_count,sizeof(*person_list));
if (person_list == NULL) {
perror("person_list");
exit(1);
}
search_list = calloc(search_count,sizeof(*search_list));
if (search_list == NULL) {
perror("search_list");
exit(1);
}
// read in coordinates of all people
for (int idx = 0; idx < person_count; ++idx) {
pt = &person_list[idx];
fscanf(fi,"%d %d",&pt->x,&pt->y);
}
// read in all search coordinates
for (int idx = 0; idx < search_count; ++idx) {
pt = &search_list[idx];
fscanf(fi,"%d %d",&pt->x,&pt->y);
}
// get the ranking
sortany(person_list,person_count,threshold,compareTo);
// remember the ranking and print the ranked list
for (int idx = 0; idx < person_count; ++idx) {
pt = &person_list[idx];
pt->rank = idx;
if (opt_d)
printf("%d %d dist=%d rank=%d\n",pt->x,pt->y,dist(pt),idx);
else
printf("%d %d\n",pt->x,pt->y);
}
// reorder list for search points
sortany(person_list,person_count,threshold,compareAbs);
// perform all queries
for (int idx = 0; idx < search_count; ++idx) {
pt = &search_list[idx];
int match = binarysearch(pt,person_list,person_count,compareAbs);
if (match < 0) {
printf("%d %d not found\n",pt->x,pt->y);
continue;
}
pt = &person_list[match];
printf("%d %d found at rank %d\n",pt->x,pt->y,pt->rank);
}
if (file != NULL)
fclose(fi);
free(person_list);
free(search_list);
return 0;
}
// gencoord -- generate a random coordinate
void
gencoord(coord_t *pt)
{
int val;
int neg;
for (int mode = 0; mode <= 1; ++mode) {
val = rand();
neg = (val & 1);
val >>= 1;
val %= (COORDMAX + 1);
if (neg)
val = -val;
if (mode == 0)
pt->x = val;
else
pt->y = val;
}
}
// genrand -- genrate a random number in the inclusive range
int
genrand(int lo,int hi)
{
int val;
val = rand();
val %= (hi + 1);
if (val < lo)
val = lo;
return val;
}
// gensame -- decide if coordinate already in use
int
gensame(coord_t *pt,coord_t *list,int length)
{
int match;
do {
// coordinate may _not_ be the starting/self point
match = (compareAbs(pt,&self) == 0);
if (match)
break;
// coordinate may not match any previous point in the list
for (int idx = 0; idx < length; ++idx) {
match = (compareAbs(pt,&list[idx]) == 0);
if (match)
break;
}
} while (0);
return match;
}
// gentest -- generate a random test file
void
gentest(FILE *fi)
{
int val;
int threshold;
int person_count;
int search_count;
int same;
coord_t *person_list;
coord_t *pt;
coord_t tmp;
gencoord(&self);
person_count = genrand(2,PERSONMAX);
search_count = genrand(1,SEARCHMAX);
threshold = genrand(1,THRESHMAX);
fprintf(fi,"%d %d %d %d %d\n",
self.x,self.y,person_count,search_count,threshold);
person_list = calloc(person_count,sizeof(*person_list));
if (person_list == NULL) {
perror("person_list");
exit(1);
}
// generate coordinates of all people
fprintf(fi,"\n");
for (int idx = 0; idx < person_count; ++idx) {
pt = &person_list[idx];
pt->rank = 0;
// ensure [proposed] coordinate is unique
same = 1;
while (same) {
gencoord(pt);
same = gensame(pt,person_list,idx);
}
fprintf(fi,"%d %d\n",pt->x,pt->y);
}
// generate search coordinates
fprintf(fi,"\n");
for (int idx = 0; idx < search_count; ++idx) {
pt = &tmp;
val = rand();
val %= 100;
// generate a random point that is _not_ a person or self (10% of the
// time)
if (val < 10) {
same = 1;
while (same) {
gencoord(pt);
same = gensame(pt,person_list,person_count);
}
}
// randomly select an infected person
else {
val = genrand(0,person_count - 1);
pt = &person_list[val];
}
fprintf(fi,"%d %d\n",pt->x,pt->y);
}
free(person_list);
}

Solve a maze backtracking

I am trying to solve a maze using backtracking in C. To solve the maze the following rules:
You begin from the position of S and need to go towards E
You can only go on '.' path
Convert all the '.' into '#' including S and E
The input consists of a m x n matrix:
Input example:
11 11
+-+-+-+-+-+
S.|...|...|
+.+.+.+-+.+
|.|.|.....|
+.+-+-+-+.+
|...|.|...|
+.+.+.+.+-+
|.|...|.|.|
+.+-+.+.+.+
|...|.....E
+-+-+-+-+-+
Expected solution :
+-+-+-+-+-+
##|...|...|
+#+.+.+-+.+
|#|.|.....|
+#+-+-+-+.+
|###|.|...|
+.+#+.+.+-+
|.|###|.|.|
+.+-+#+.+.+
|...|######
+-+-+-+-+-+
I am trying really hard to solve it but for some reason my program doesn't go back once I reached a point in the maze from where I can't go further.It just go in all the directions where it sees a '.'
My idea was to start from the position of S and using at each recursion step the old position that we were.
I will go in all the direction from the position where I am standing if the position that I am looking at is a '.' and if that point was not my old position.
I also think that I have a problem when i reach a point where it was a crossroad when I backtrack. For example:
+-+-+-+-+-+
##|...|...|
+#+.+.+-+.+
|#|.|.....|
+#+-+-+-+.+
|0##|.|...|
+.+#+.+.+-+
|.|###|.|.|
+.+-+#+.+.+
|..1|######
+-+-+-+-+-+
Imagine that I am in the position 0. And I backtracked from 1 changing back the # into '.'.How can I make a statement saying that you have 2 # possibilities to go back , yet you should stop?
My code :
#include <stdio.h>
#include <stdlib.h>
void *safeMalloc(int n) {
void *p = malloc(n);
if (p == NULL) {
printf("Error: malloc(%d) failed. Out of memory?\n", n);
exit(EXIT_FAILURE);
}
return p;
}
char ** readMatrix(int m,int n,int* startI,int* startJ,int* endI,int* endJ){
char **arr = safeMalloc(m*sizeof(char *));
int row;
for (row=0; row < m; row++) {
arr[row] = safeMalloc(n*sizeof(char));
}
int i,j;
for(i=0;i<m;i++){
for(j=0;j<m;j++){
scanf(" %c",&arr[i][j]);
if(arr[i][j]=='S'){
*startI=i;
*startJ=j;
}
if(arr[i][j]=='E'){
*endI=i;
*endJ=j;
}
}
getchar();
}
return arr;
}
void printNumber(char **arr,int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%c", arr[i][j]);
}
printf("\n");
}
}
void findPath(char** arr,int m,int n,int startI,int startJ,int endI,int endJ,int oldI,int oldJ){
int i=startI,j=startJ;
int stepsPossible=4;
//going up
if(i-1>=0){
if((arr[i-1][j]=='.') && ((i-1!=oldI) || (j!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i-1,j,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//going right
if(j+1<n){
if((arr[i][j+1]=='.') && ((i!= oldI) || (j+1!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j+1,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//going left
if(j-1>=0){
if((arr[i][j-1]=='.') && ((i!= oldI) || (j-1!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j-1,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//going down
if(i+1<m){
if((arr[i+1][j]=='.') && ((i+1!= oldI) || (j!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i+1,j,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//if the next block is E then we can stop.
if((arr[i-1][j]=='E') || (arr[i][j+1]=='E') || (arr[i][j-1]=='E') || (arr[i+1][j]=='E')){
if(arr[i-1][j]=='E'){
arr[i-1][j]='#';
}
if(arr[i][j+1]=='E'){
arr[i][j+1]='#';
}
if(arr[i][j-1]=='E'){
arr[i][j-1]='#';
}
if(arr[i+1][j]=='E'){
arr[i+1][j]='#';
}
return;
}
if(stepsPossible==0){
if(arr[i-1][j]=='#'){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i-1,j,endI,endJ,oldI,oldJ);
}else{
return;
}
if(arr[i][j+1]=='#' ){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j+1,endI,endJ,oldI,oldJ);
}else{
return;
}
if(arr[i][j-1]=='#' ){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j-1,endI,endJ,oldI,oldJ);
}else{
return;
}
if(arr[i+1][j]=='#' ){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i+1,j,endI,endJ,oldI,oldJ);
}else{
return;
}
}
}
int main()
{
int m,n;
scanf("%d %d",&m,&n);
int startI,startJ,endI,endJ;
char** arr;
arr=readMatrix(m,n,&startI,&startJ,&endI,&endJ);
findPath(arr,m,n,startI,startJ,endI,endJ,startI,startJ);
printNumber(arr,m,n);
return 0;
}
Make proper use of the return value, as you can utilize it to simplify your logic. Choose different return values on findPath for the error case (backtracking necessary) and the success case (end reached).
Now you can put setting the # unconditionally in the start of that function, and resetting back to . unconditionally in the end for the backtracking case.
There is no need to count possible directions either, only checking if some call returned success.
Also no need to write the boundary checks over and over again, if you just check them at the start of the function you can just pass invalid coordinates without any issues.
bool findPath(char** arr, size_t sx, size_t sy, int x, int y) {
if (x < 0 || x >= sx || y < 0 || y >= sy) return false;
if (arr[x][y] == 'E') {
are[x][y] = '#';
return true;
}
if (arr[x][y] != '.') return false;
arr[x][y] = '#';
bool success = findPath(arr, sx, sy, x-1, y) ||
findPath(arr, sx, sy, x+1, y) ||
findPath(arr, sx, sy, x, y-1) ||
findPath(arr, sx, sy, x, y+1);
if (!success) arr[x][y] = '.';
return success;
}
Implementations for backtracking algorithms usually all follow the same pattern:
Try to either trivially reject or accept the current solution.
Modify the current solution.
Try variations.
Clean up the modifications if not successful.
I would suggest to use BFS because
BFS will find the shortest solution.
DFS handles certain mazes very very poorly.
Here is short description of BFS for your case:
Find 'S' in your maze and add it into queue
While queue is not empty check get element from queue.
Replace element with "#". If element is E, you are done. Check neighbours(up, down, left right) of the element, if they are ".", then add into queue.
If queue is empty and E not found, then there is no direct path from S to E

Iterator and Pointer on Matrix in C

For a JPEG image compression, I manipulate image in grey levels and 8bits by pixels
I have this type of matrix I dynamically allocated :
typedef char pixel_t;
pixel_t ** pix_matrix;
after allocating and filling it, I have a bidimensional array with the values (from -128 to +127) of the luminance of the picture.
For the JPEG compression, I need to iterate this array in zigzag like this:
So I want to create an Iterator structure for this type. This iterator must have 'current' and 'begin' members and I want those members to be pointers to the current element and first one of the matrix. In other words, I want to store the addresses and not the indexes. But after hours of tests, prints and researches, I couldn't find the way to make that possible. What type of pointer do I have to use? how make it point to the first address of my matrix? Is my request simply possible?
And if all of this is possible, how can I get the next element, and the value of the current one?
You can write an interator structure:
struct zigzag_t {
int width; // width, must be initialised
int height; // height, must be initialised
int x; // current x index
int y; // current y index
int underway; // dummy value to start at (0, 0)
};
which you must initialise with the width and height of your image. Write an interator function, so that you can use this iterator like this:
struct zigzag_t zz = {8, 8};
while (zigzag_next(&zz)) {
printf("(%d, %d)\n", zz.y, zz.x);
}
The iterator itself is not too complicated: If the sum of the x and y indices is odd, you walk southwest until you hit either the west or south edge. If the sum is even, you walk northeast until you hit either the north or east wall. If you hit the ne or sw edges, the east and south edges get priority. The iteration ends after you have visited the se edge.
Because the struct starts off with x and y both zero, the first point is (0, 1). In order to fix this, the dummy field underway, which also is zero, is used.
The iterator must be reset if you want to use it a second time. better yet, define and initialise a fresh iterator.
The iterator function:
int zigzag_next(struct zigzag_t *zz)
{
int odd = (zz->x + zz->y) % 2;
if (zz->underway == 0) {
zz->x = zz->y = 0;
zz->underway = 1;
return 1;
}
if (odd) {
/* walk southwest */
int w_edge = zz->x == 0;
int s_edge = zz->y == zz->height - 1;
if (s_edge) {
zz->x++;
return zz->x < zz->width;
} else if (w_edge) {
zz->y++;
} else {
zz->x--;
zz->y++;
}
} else {
/* walk northeast */
int e_edge = zz->x == zz->width - 1;
int n_edge = zz->y == 0;
if (e_edge) {
zz->y++;
return zz->y < zz->height;
} else if (n_edge) {
zz->x++;
} else {
zz->x++;
zz->y--;
}
}
return 1;
}
This solution returns the x and y positions, which you can use as indices to your double pointer to pixel data. It would not be hard to extend the struct to hold the base pointer to your pixel data and have the iterator function return a pointer to a pixel or NULL if the iteration has run out.
An example solution with pointers is below.
#include <stdlib.h>
#include <stdio.h>
typedef char pixel_t;
struct zigzag_t {
pixel_t **p; // base data
int width; // width, must be initialised
int height; // height, must be initialised
int x; // current x index
int y; // current y index
int underway; // dummy value to start at (0, 0)
};
pixel_t *zigzag_next(struct zigzag_t *zz)
{
int odd = (zz->x + zz->y) % 2;
if (zz->underway == 0) {
zz->x = zz->y = 0;
zz->underway = 1;
return *zz->p;
}
if (odd) {
/* walk southwest */
int w_edge = zz->x == 0;
int s_edge = zz->y == zz->height - 1;
if (s_edge) {
zz->x++;
if (zz->x == zz->width) return NULL;
} else if (w_edge) {
zz->y++;
} else {
zz->x--;
zz->y++;
}
} else {
/* walk northeast */
int e_edge = zz->x == zz->width - 1;
int n_edge = zz->y == 0;
if (e_edge) {
zz->y++;
if (zz->y == zz->height) return NULL;
} else if (n_edge) {
zz->x++;
} else {
zz->x++;
zz->y--;
}
}
return zz->p[zz->y] + zz->x;
}
int main()
{
pixel_t *data[] = {
"abcde", "fghij", "klmno", "pqrst", "uvwxy"
};
struct zigzag_t zz = {data, 5, 5};
for (;;) {
pixel_t *p = zigzag_next(&zz);
if (p == NULL) break;
putchar(*p);
}
putchar('\n');
return 0;
}
This solution is a C solution. There is no begin member function; initialisation is done via simple struct initialisation. There is no increment operator and no end member function; moving the iterator forward and checking for the end is done in a plain old function.
You have tagged the question C, but iterators are more frequent in C++, where they can be implemented as classes. The above C example may serve as a base for such an implementation.
Something nice and simple.
Function next is the iterator; it returns true until all cells have been visited.
A variable of type POSITION holds the iterator state.
Function current returns a pointer to the current cell in the matrix.
Demo function sample_application puts it all together.
#define MAX_XY 7
typedef struct { int x, y; } POSITION;
static int sign_of(int i)
{
return i < 0 ? -1 : i > 0 ? 1 : 0;
}
static int get_direction(int a, int b, int odd_is_forward)
{
return sign_of(((a + b) % 2 == odd_is_forward || b >= MAX_XY ? MAX_XY : 0) - a);
}
int next(POSITION *pos)
{
int x = pos->x;
int y = pos->y;
pos->x += get_direction(x, y, 0);
pos->y += get_direction(y, x, 1);
return x < MAX_XY || y < MAX_XY;
}
pixel_t *current(POSITION *pos)
{
return &pix_matrix[pos->y][pos->x];
}
void sample_application() // just demonstrating the use of POSITION
{
POSITION pos = {-1, -1}; // always start from these dummy coordinates
while (next(&pos)) // this iterates through the matrix
{
int coord_x = pos.x; // this is how you get the current coordinates
int coord_y = pos.y;
*current(&pos) = 12; // this is how you access the current cell
}
}

How can I do this again? in C

#define G 10
int main(){
int grid[G][G],c,x;
for(c=1;c<=5;c++){
for(x=1;x<=5;x++){
if(c+x<=5)
grid[c][x]=+1;
else if(c+x>=7)
grid[c][x]=-1;
else
grid[c][x]=0;
printf("%2d\t ",grid[c][x]);
}
printf("\n");
}
getch();
return 0;
}
its output is
Which is what I really wanted to do but now I need to make it look like
and now I don't have any idea on how to do it, it's hurting my head now
I would do it like this
for(c=0; c<5; c++) { /* arrays start at 0, not 1. */
for(x=0; x<5; x++) { /* arrays start at 0, not 1. */
if (c == x) { /* looking at your output, the 0's occur when c == x */
grid[c][x] = 0;
} else if (c > x) { /* the -1 when c > x */
grid[c][x] = -1;
} else { /* obviously c > x */
grid[c][x] = 1;
}
/* nothing else changed */
printf("%2d\t ",grid[c][x]);
}
printf("\n");
}
It's quite simple, you have three distinct cases:
if both c and x are equal, your grid shows zero
if x is greater than c, your grid shows 1
else (ie, when x is less than c), your grid shows -1
Basically, we've written the if-else structure you need in your loop to get the desired output:
if (c == x) grid[c][x] = 0;
else if (x > c) grid[c][x] = 1;
else grid[c][x] = -1;
Thus, the full code looks like this:
#include <stdio.h>
#define G 10
int main()
{
int grid[G][G],c,x;
for(c=0;c<5;++c)
{//zero indexed
for(x=0;x<5;++x)
{//perhaps change 5 with G, or another macro or some int
if(c == x) grid[c][x] = 0;
else if (c < x) grid[c][x] = 1;//1 is fine, the + is not required
else grid[c][x] = -1;
printf("%2d\t ",grid[c][x]);
}
printf("\n");
}
return 0;
}
Which as you can see on this codepad works just fine.
note:
As I said, the + in +1 is optional. I'd even advise against it. If I happen to come across a statement like some_int = +1; I might assume that it's a bug, and it was supposed to read some_int += 1;, which is a different thing all together.
The major diagonal of matrix is collection of elements that meet row==column condition. Plus we know that row and column elements above(right from) diagonal meet row<column, and below ones row>column condition. And here is how to make that matrix and while making we will show them :
#define G 5
int grid[G][G], row, column;
for (row =0; row < G; row++) {
for (column =0; column < G; column++) {
if (row<column)
grid[row][column] = 1;
else if (row>column)
grid[row][column] = -1;
else
grid[row][column] = 0;
printf("%2d\t ", grid[row][column]);
}
printf("\n");
}
And here is output:
0 1 1 1 1
-1 0 1 1 1
-1 -1 0 1 1
-1 -1 -1 0 1
-1 -1 -1 -1 0
And Here is what was your problem.
You chose minor (secondary) diagonal isntead of main
Your index handling done manually .Like you calculated conditions manually. It is not good
And here is how you should do for minor diagonal without calculating condition manually
#define G 5
int grid[G][G], row, column ;
for(row=0;row<G;row++){
for(column=0;column< G;column++){
if(row+column<G-1)
grid[row][column]=1;
else if(row+column>G-1)
grid[row][column]=-1;
else /*minor diagonal meet row==(G-1)-column //G-1 cause index begins from 0*/
grid[row][column]=0;
printf("%2d\t ",grid[row][column]);
}
printf("\n");
}
Now Swap the first and last columns of your matrix then second and second last. Thats it
#include <stdio.h>
#define G 10
int i,j;
int grid[G][G];
int main() {
for(i=0; i<G; i++) {
for(j=0; j<G; j++) {
if(i==j) grid[i][j]=0;
else if(i<j) grid[i][j]=1;
else if(i>j) grid[i][j]=-1;
printf("%2d\t", grid[i][j]);
}
printf("\n");
}
return 0;
}
you can modify your program as below :
1,for(c=1;c<=5;c++) -->for(c=5;c>=1;c--)
2, grid[c][x]=+1; --> grid[c][x]=-1;
3, grid[c][x]=1; --> grid[c][x]=+1;
#define G 10
int main(){
int grid[G][G],c,x;
for(c=5;c>=1;c--){
for(x=1;x<=5;x++){
if(c+x<=5)
grid[c][x]=-1;
else if(c+x>=7)
grid[c][x]= 1;
else
grid[c][x]=0;
printf("%2d\t ",grid[c][x]);
}
printf("\n");
}
getch();
return 0;
}
You need to create a 2D matrix, where the matrix is diagonally zero, upper triangle would be 1, and lower triangle would be -1.
So,
if **row == column** , then assign 0 to diagonal. (**grid[row][column] = 0**)
else if , **row < column**, then assign 1 to upper triangle. (*grid[row][column*] = 1)
else, **row > column**, then assign -1 to lower triangle. (*grid[row][column] = -1*)

Resources