Consider the following declaration:
typedef struct {
    int V;
    int E;
    int **Adj;
} Graph;
Given a $$\texttt{start string}$$, $$\texttt{end string}$$ and a $$\texttt{set of strings}$$, find if there exists a path between the $$\texttt{start string}$$ and $$\texttt{end string}$$ via the $$\texttt{set of strings}$$.
A path exists if we can get from $$\texttt{start string}$$ to $$\texttt{end string}$$ by changing (no addition/removal) only one character at a time. The restriction is that the new string generated after changing one character has to be in the set. 

Example
$$\texttt{start string}$$: "cog" 
$$\texttt{end string}$$ : "bad"
$$\texttt{set of strings}$$: ["bag", "cag", "cat", "fag", "con", "rat", "sat", "fog"]
One of the paths: "cog" $$\rightarrow$$ "fog" $$\rightarrow$$ "fag" $$\rightarrow$$ "bag" $$\rightarrow$$ "bad"


Difficulty level
Video recording
This exercise is mostly suitable for students
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100

typedef struct {
	int V;
	int E;
	int **Adj; // since we need 2 dimensional matrix
} Graph;

typedef int element;

typedef struct 
{
	element data[N]; /* queue content */
	int front, length;
} queue;


queue CreateQueue()
{
	queue q;
	q.front = 0; q.length=0;
	return q;
}
int isEmptyQueue(queue q)
{
	return q.length == 0;
}

int isFullQueue(queue q)
{
	return q.length ==N;
}

int EnQueue(queue *q, element e)
{
	if (isFullQueue(*q)) return 0;
	q->data[(q->front + q->length)%N] = e;
	q->length = q->length + 1;
	return 1;
}

int DeQueue(queue *q)
{
	if (isEmptyQueue(*q)) return 0;
	q->front=(q->front + 1) % N;
	q->length--;
	return 1;
}

int Front(queue q, element *e)
{
	if (isEmptyQueue(q)) return 0;
	*e = q.data[q.front];
	return 1;
}

 
int string_difference(char *s1, char *s2)
{
	int diff = 0;
	while (*s1 != '\0')
		if (*s1++ != *s2++)
			diff++;
	return diff;
}

int pathExist(char* set[], int size, int start, int end) {
	int i, j, u, v, w;
	queue q;
	int *Visited;
 
	Graph* G = (Graph*)malloc(sizeof(Graph));
	G->V = size;
	G->E = size;
	Visited = (int *)malloc(G->V * sizeof(int));
	G->Adj = (int **)malloc(G->V * sizeof(int*));
	for (u = 0; u < G->V; u++)
	{
		G->Adj[u] = (int *)malloc(G->V * sizeof(int));
		Visited[u] = 0;
		for (v = 0; v<G->V; v++)
			G->Adj[u][v] = 0;
	}

	for(i=0;i<size;i++)
		for(j= i+1;j<size;j++)
			if(string_difference(set[i], set[j])==1)
			{
				G->Adj[i][j] = 1;
				G->Adj[j][i] = 1;
			}
 
	q = CreateQueue();
	EnQueue(&q, start);
	while (Front(q, &v)) {
		DeQueue(&q);
		if (v == end)
			return 1;
		Visited[v] = 1;
		for (w = 0; w < G->V; w++)
			if (!Visited[w] && G->Adj[v][w])
				EnQueue(&q, w);
	}
	return 0;
}


 
void test() {
    int size , i, istr1, istr2, ans;
    char **set , str1[20], str2[20];
    
    
    printf("Enter the number of words: ");
    scanf("%d", &size);
    set = (char **)malloc(size * sizeof(char*));
    for(i=0;i<size;i++)
    {
        printf("Enter word %d: ", i+1);
        scanf("%s", str1);
        set[i] = (char *)malloc(strlen(str1) * sizeof(char*));
        strcpy(set[i],str1);
    }
    printf("Enter beginning and ending words: ");
    scanf("%s %s", str1, str2);
    
    //find index of str1 and str2
    for(i=0;i<size;i++)
		if (strcmp(str1, set[i]) == 0)
			istr1 = i;
		else
			if (strcmp(str2, set[i]) == 0)
				istr2 = i;
	
	
	if (pathExist(set, size, istr1, istr2))
		printf("Path Exists\n");
	else
		printf("Path doesn't Exists\n");
}


int  main()
{
	test();
	return 0;
}

Back to the list of exercises
Looking for a more challenging exercise, try this one !!
Forest of Binary Search Trees