Sukrit Kapil
Sukrit Kapil

Reputation: 35

Why isn't the code coming out of recursion?

The problem is to find the number of times a word occurs in a given N x N matrix of alphabets. We can move from any cell to other adjacent cell. The first line has one integer N and then a N x N matrix. Next line has M (size of the word) and then a string to be found in the matrix.

Input:
4
ABCD
ABCD
ABCD
ABCD
2
BC

Expected output:
10

I have written the following code for the same and used recursion for solving the problem. The function adj checks if the character is adjacent in the matrix with the previous character using their indexes. The function check increases the count whenever the string is completed. The 2-d array keeps a check on the visited and unvisited elements.

I am getting the output as

OUPUT
1

EDIT 1: This output is just because of the debugging print statement, so the if statement is being visited only once. It does not mean that the count variable is 1 after many recursion calls.

EDIT 2: There shouldn't be & in the scanf statement for word. But still the output is not the desired one.

EDIT 3:

Another input
7
SHELDON
HSTYUPQ 
EHGXBAJ
LMNNQQI
DTYUIOP
OZXCVBN
NQWERTY
7
SHELDON

Expected output:
5

My output - 1

EDIT 4(Solved!): So the problem was in writing the no. of columns as 500 for the grid matrix, changing it to 5 did the job! Thanks to @gsamaras

Code

#include <stdio.h>

int vis[500][500], count;

int adj(int a, int b, int c, int d) {
    if((c == a - 1) && (d == b - 1)) {
        return 1;
    }
    else if((c == a - 1) && (d == b)) {
        return 1;
    }
    else if((c == a) && (d == b - 1)) {
        return 1;
    }
    else if((c == a - 1) && (d == b + 1)) {
        return 1;
    }
    else if((c == a + 1) && (d == b)) {
        return 1;
    }
    else if((c == a + 1) && (d == b + 1)) {
        return 1;
    }
    else if((c == a) && (d == b + 1)) {
        return 1;
    }
    else if((c == a + 1) && (d == b - 1)) {
        return 1;
    }
    else {
        return 0;
    }

}

void check(char grid[][500],int i, int j, int id, char word[], int n, int m) {
    if(id == m) {
        count++;
        printf("%d\n", count); // just to debug
    }
    else {
        for(int p = 0; p < n; p++) {
            for(int q = 0;q < n; q++) {
                if((grid[p][q] == word[id]) && (adj(i, j, p, q)) && (vis[p][q] != 1)) {
                    vis[p][q] = 1;
                    check(grid, p, q, id + 1, word, n, m);
                    vis[p][q] = 0;
                }
            }
        }
    }
}

int main() {
    int n, m, id = 0;
    char blank;
    scanf("%d", &n);
    scanf("%c", &blank);
    char grid[n][n+1];
    for(int i = 0; i < n; i++) {
        scanf("%s", grid[i]);
        grid[i][n] = '\0';
    }
    scanf("%d", &m);
    char word[m+1];
    scanf("%s", &word);

    for(int i = 0; i < n; i++) {
        for(int j = 0;j < n; j++) {
            if(grid[i][j] == word[id]) {
                vis[i][j] = 1;
                check(grid, i, j, id + 1, word, n, m);
                vis[i][j] = 0;
            }
        }
    }
    printf("%d\n", count);
    return 0;
}

Upvotes: 1

Views: 94

Answers (1)

gsamaras
gsamaras

Reputation: 73366

Change this:

void check(char grid[][500], ......

to this:

void check(char grid[][5], .......   // that should be equal to N + 1 (5 in your case)

since your grid is of size N x N + 1. With the 500 as the dimension, you distorted the grid, and when trying to search into it recursively, you wouldn't traverse the grid that you would expect to traverse..

As you see this is not flexible, since N can vary. You cannot declare grid as global, since its dimensions are not fixed. Dynamic memory allocation should be used instead.


Change this:

scanf("%s", &word);

to this:

scanf("%s", word);

since word is an array of characters.


Complete example with Dynamic Memory Allocation:

#include <stdio.h>
#include <stdlib.h>

int vis[500][500], count;

char **get(int N, int M) { /* Allocate the array */
    int i;
    char **p;
    p = malloc(N*sizeof(char *));
    for(i = 0 ; i < N ; i++)
        p[i] = malloc( M*sizeof(char) );
    return p;
}

void free2Darray(char** p, int N) {
    int i;
    for(i = 0 ; i < N ; i++)
        free(p[i]);
    free(p);
}

int adj(int a, int b, int c, int d) {
    // Same as in your question
}

void check(char** grid, int i, int j, int id, char word[], int n, int m) {
    if(id == m) {
        count++;
        printf("count = %d\n", count); // just to debug
    }
    else {
        for(int p = 0; p < n; p++) {
            for(int q = 0;q < 499; q++) {
              //printf("p = %d, q = %d, id = %d, grid[p][q] = %c, word[id] = %c\n", p, q, id, grid[p][q], word[id]);
                if((grid[p][q] == word[id]) && (adj(i, j, p, q)) && (vis[p][q] != 1)) {
                    vis[p][q] = 1;
                    check(grid, p, q, id + 1, word, n, m);
                    vis[p][q] = 0;
                }
            }
        }
    }
}

int main() {
    int n, m, id = 0;
    char blank;
    scanf("%d", &n);
    scanf("%c", &blank);
    char** grid = get(n, n + 1);
    for(int i = 0; i < n; i++) {
        scanf("%s", grid[i]);
        grid[i][n] = '\0';
    }
    scanf("%d", &m);
    char word[m+1];
    scanf("%s", word);

    for(int i = 0; i < n; i++) {
        for(int j = 0;j < n; j++) {
            //printf("i = %d, j = %d, id = %d\n", i, j, id);
            if(grid[i][j] == word[id]) {
                vis[i][j] = 1;
                check(grid, i, j, id + 1, word, n, m);
                vis[i][j] = 0;
            }
        }
    }
    printf("%d\n", count);

    free2Darray(grid, n);
    return 0;
}

Output (for your 1st input):

count = 1
count = 2
count = 3
count = 4
count = 5
count = 6
count = 7
count = 8
count = 9
count = 10
10

PS: Not a problem, just a suggestion about readability: count is initialized to 0, because it's a global variable, but it's always best to explicitly initialize your variables, when it matters.

Upvotes: 2

Related Questions