Solve a maze backtracking - c

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

Related

C Recursion segmentation fault

I am new to C and trying to do a maze problem where 0 and letters are passing points and 1 is a barrier.
My 2D maze array are below where the starting point is at(0,4) and every time I have to check for 4 directions (N,S,E,W), and I have also the path array (initially contains "0" as chars) where I will put the routes as "R" which is also the same size:
1111S11110
0000010001
110100010d
t001111110
0100000001
0111111101
1111111101
00000D01T1
0111110001
0000E01110
I am using recursive solution for pathfinding and in total use 3 functions which are below:
int isSafe(char Mazearray[matrixSize][matrixSize],int x,int y){
if(x >= 0 && x < matrixSize && y >= 0 && y < matrixSize && Mazearray[x][y] != '1'){
return 1;
}
return 0;
}
void MazeSolution(char Mazearray[matrixSize][matrixSize],int x,int y,char pathArray[matrixSize][matrixSize]){
if(recursiveMaze(Mazearray,x,y,pathArray) == 0){
printf("There does not exist a possible solution!!!");
}
else{
int i,j;
for (i = 0; i < matrixSize; ++i){
for (j = 0; j < matrixSize; ++j){
printf("%c",pathArray[i][j]);
}
printf("\n");
}
}
}
int recursiveMaze(char Mazearray[matrixSize][matrixSize],int x,int y,char pathArray[matrixSize][matrixSize]){
if(x == exitX && y == exitY){
pathArray[x][y] == 'E';
return 1;
}
// check if the coordinate is safe to go(not 1)
if(isSafe(Mazearray,x,y) == 1){
pathArray[x][y] == 'R';
// Move North
if(recursiveMaze(Mazearray,x-1,y,pathArray) == 1){
return 1;
}
// Move South
if(recursiveMaze(Mazearray,x+1,y,pathArray) == 1){
return 1;
}
// Move East
if(recursiveMaze(Mazearray,x,y+1,pathArray) == 1){
return 1;
}
// Move West
if(recursiveMaze(Mazearray,x-1,y-1,pathArray) == 1){
return 1;
}
pathArray[x][y] == '0';
return 0;
}
return 0;
}
When I run the MazeSolution(), the program terminates with error code 255 and segmentation fault. When I debugged the problem appears at recursiveMaze() function.
So that, starting from first if statement it does not execute and the other problem is it goes and comes back between south and north control points.
Here is a call sequence that leads to an infinite loop:
recursiveMaze(M, x, y, p)
recursiveMaze(M, x-1, y, p)
recursiveMaze(M, x-1, y, p) -> run to completion
recursiveMaze(M, x+1, y, p) -> infinite loop
It is infinite because in the second recursive call, you increment back the value that had been decremented in the first recursive call, which takes you back to the same state as the initial call.

Subset using Backtracking

The following question I was asked to solve using backtracking:
It's supposed to return the length of the longest subset of differences that replaces a sign.
For example:
for this given series [11,6,7,8,9] it returns 3.
because it includes this subset [11,8,9] and [11,6,8] .
*In this series a:[11,8,9] a[1]-a[0]<0 and a[2]-a[1]>0 .In other words the sign of the difference between each neighbor changes. *
I pretty much finished the coding but have no idea how to return the max length using backtracking.
Any note/help will be highly appreciated.
/* this function checks if we can add another number to the sequence
and still the differences between the numbers replace a sign.It's enough
to check the last two*/
int check_rec(int series[],int arr[],int n)
{ int count=0,c=n;
int temp1=0,temp2=0;
while(c>=0 && count!=2)
{
if (arr[c]==1 && count==0)
{ temp1=series[c];
count++;
}
if (arr[c]==1 && count==1 )
{ temp1=series[c];
count++;
}
c--;
}
if(count<2) return 1;
if(temp1>temp2 && series[n+1] < temp1) return 1;
if(temp1<temp2 && series[n+1]> temp1) return 1;
return 0;
}
int count_ones(int arr[],int n)
{ int c;
for(int i=0;i<n;i++)
{
if(arr[i])
c++;
}
return c;
}
// 1 in the array helper indicates that the index has been chosen.
void max_crazy(int series[], int n,int helper[],int length,int max[])
{
if(n==0)
{
int x=count_ones(helper,n);
if(x>max[0])
max[0]=x;
}
for(int i=0;i<2;i++)
{
if(n!=length && i==1 && !check_rec(series,helper,length-n))
continue;
helper[0]=i;
max_crazy(series,n-1,helper+1,length,max);
}
}
you can send a pointer that saves the max in the recursive function , and every time you reach the if(n==0) you have to check if the count_ones bigger than max then max=count_ones

Search of an element on a unsorted array recursively

This is an exercise that I took from an exam. It asks to write a function that receives an unsorted array v[] and a number X and the function will return 1 if X is present in v[] or 0 if X is not present in v[]. The function must be recursive and must work in this manner:
1. Compares X with the element in the middle of v[];
2. The function calls itself (recursion!!) on upper half and on the lower half of v[];
So I've written this function:
int occ(int *p,int dim,int X){
int pivot,a,b;
pivot=(dim)/2;
if(dim==0) //end of array
return 0;
if(*(p+pivot)==X) //verify if the element in the middle is X
return 1;
a=occ(p,pivot,X); //call on lower half
b=occ(p+pivot,dim-pivot,X); //call on upper half
if(a+b>=1) //if X is found return 1 else 0
return 1;
else{
return 0;
}
}
I tried to simulated it on a sheet of paper and it seems to be correct (Even though I'm not sure) then I've written it on ideone and it can't run the program!
Here is the link: https://ideone.com/ZwwpAW
Is my code actually wrong (probably!) or is it a problem related to ideone. Can someone help me? Thank you in advance!!!
The problem is with b=occ(p+pivot,dim-pivot,X); when pivot is 0. i.e. when dim is 1.
the next function call becomes occ(p,1,X); This again leads to the call occ(p,1,X); in a continuous loop.
It can be fixed by adding a condition to the call, as shown in the code below.
int occ(int *p,int dim,int X){
int pivot,a=0,b=0;
pivot=(dim)/2;
if(dim==0){
return 0;
}
if(*(p+pivot)==X)
return 1;
if (pivot != 0)
{
a=occ(p,pivot,X);
b=occ(p+pivot,dim-pivot,X);
}
if(a+b>=1)
return 1;
else{
return 0;
}
}
The implemetation is causing a stack overflow, as the recursion does not terminate if the input contains only one element. This can be fixed as follows.
int occ(int *p, int dim, int X)
{
int pivot, a, b;
pivot = (dim) / 2;
if (dim == 0)
{
return 0;
}
if (*(p + pivot) == X)
{
return 1;
}
if (dim == 1)
{
if (*(p + pivot) == X)
{
return 1;
}
else
{
return 0;
}
}
a = occ(p, pivot, X);
b = occ(p + pivot, dim - pivot, X);
if (a + b >= 1)
{
return 1;
}
else
{
return 0;
}
}
It's enought to change only this one line in the source code to avoid the endless loop with occ(p,1,X):
//if(dim==0) //end of array
if (pivot == 0)
return 0;

Find number of paths in a 2d binary array (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.

C- Fix Stack overflow in Recursion

A code in C to find maximum of an array using divide and conquer but it keeps throwing
"stack overflow exception" . Help would be appreciated!
int a[10];
int find(int l,int h)
{
int x;
if(h==0)
{
x=0;
return x;
}
else
{
if(h==1)
{
if(a[0]>a[1])
{
x=0;
return x;
}
else
{
x=1;
return x;
}
}
else
{
int mid,z,y;
mid=(l+h)/2;
y=find(0,mid);
z=find(mid+1,h);
if(a[y]<a[z])
{
x=z;
}
else
{
x=y;
}
return x;
}
}
}
There are only limited variables and I don't see where the function can go into an infinite recursion.
int main()
{
int i,n,max,min,ans;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
ans=find(0,n-1);
printf("the maximum element is- %d\n",ans);
getch();
return 0;
}
Consider the case where you call find(0, 2). Since h > 1, you enter the second else clause, and mid is 1. Then on the second recursive call, it is to find(2, 2). On this recursive call, you again enter the second else, since h is still 2. But the mid is also 2. Now, the first recursive call goes to find(0, 2), which enters an infinite loop.
find(0, 2)
h not 0
h not 1
mid = 1
find(0, 1)
find(2, 2)
h not 0
h not 1
mid = 2
find (0, 2) <-- loop
It seems the intention of the if checks on h is to prevent the mid calculation from being the same as l. If so, then you can calculate the mid variable at the top of your function, and use that as the stopping condition.
It looks like this is an attempt to use divide and conquer to locate the position of the maximum element in the array a. If so, then your first recursive call should restrict itself to the range of [l..mid] instead of going back to 0.
Putting it all together:
int find(int l,int h)
{
int mid = (l+h)/2;
if (mid == l)
{
return (a[l] > a[h]) ? l : h;
}
else
{
int y = find(l, mid);
int z = find(mid+1, h);
return (a[y] > a[z]) ? y : z;
}
}
Here is your code modified, which is running successfully..
The problem is that you weren't checking the difference between l and h but only the value of h...
#include <iostream>
using namespace std;
int a[10];
int find(int l,int h)
{
int x;
if(h-l==0)
{
return h;
}
else
{
if(h-l==1)
{
if(a[l]>a[l+1])
{
return l;
}
else
{
return l+1;
}
}
else
{
int mid,z,y;
mid=(l+h)/2;
y=find(0,mid);
z=find(mid+1,h);
if(a[y]<a[z])
{
x=z;
}
else
{
x=y;
}
return x;
}}}
int main()
{
a[0]=3;
a[1]=7;
a[2]=5;
cout<<find(0,2)<<endl;
return 0;
}
you're using wrong conditions, try:
first if: if(h==l)
second if: if(h-l==1)
third if:
if(a[h]>a[l]) {
return h;
} else {
return l;
}

Resources