Dijkstras algorithm implementation in C giving wrong (but almost right) output - c

I am trying to implement Dijkstras algorithm in c and I almost have the right output. Something is happening it the dist array. It is giving extremely large and small numbers.
Link to site I'm basing most of my algorithm code on: https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/ this also explains the algorithm if you're not familiar.
Here is the code:
#include <limits.h>
#include <stdio.h>
#include<stdbool.h>
#define N 10 /* max matrix size is 10 x 10 */
#define INF INT_MAX /* infinity? */
int src; /* global */
void getdata(int amtrx[3][N], int *n, int *src) {
int i, j, nsz, nedg, fr, to, vtx, wt;
scanf("%d %d %d", &nsz, &nedg, &vtx);
for (i = 0; i < nsz; i++)
for (j = 0; j < nsz; j++)
amtrx[i][j] = INF;
for(i=0; i < nedg; i++) {
scanf("%d %d %d", &fr, &to, &wt);
amtrx[fr][to] = wt;
}
*n = nsz;
*src = vtx;
}
void printpaths(int dist[], int n) {
int i;
for (i = 0; i < n; i++)
if(i == src);
else if (dist[i] < INF) {
printf("%d %d %d\n", src, i, amtrx[i]);
} else {
printf("%d %d INF (no path)\n", src, i);
}
}
void dijkstras(int amtrx[][N], int n) {
int dist[n], v;
bool spt[n];
int min = INF, u;
for (v = 0; v < n; v++)
if (spt[v] == false && dist[v] <= min) {
min = dist[v], u = v;
spt[u] = true;
}
for (v = 0; v < n; v++)
if (!spt[v] && amtrx[u][v] != INF && dist[u] != INF && dist[u] + amtrx[u][v] < dist[v])
dist[v] = dist[u] + amtrx[u][v];
printpaths(dist, n);
}
int main() {
int amtrx[N][N];
int n;
getdata(amtrx, &n, &src);
dijkstras(amtrx, n);
return 0;
}
Here is the input:
6 11 0
0 1 50
0 2 10
0 4 45
1 2 15
1 4 10
2 0 20
2 3 15
3 1 20
3 4 35
4 3 30
5 4 03
Output:
0 1 32701
0 2 -1996178040
0 3 -1996178014
0 4 -1996178044
0 5 32765
Expected output:
0 1 45
0 2 10
0 3 25
0 4 45
0 5 INF (no path)
Thanks for the help in advance! I'm hoping it's just a simple fix that I can't seem to see :)
update
I think the algorithm was wrong and I worked on it a little, the output is still wrong but i think this is more right than before:
void dijkstras(int amtrx[][N], int n) {
int dist[n], v, q;
bool spt[n];
int min = INF, u;
for (v = 0; v < n; v++) {
dist[v] = INF;
spt[v] = false;
}
dist[n] = 0;
for (v = 0; v < n - 1; v++) {
for (q = 0; q < n; q++) {
if (spt[v] == false && dist[v] <= min) {
min = dist[v], u = v;
}
spt[u] = true;
}
for (v = 0; v < n; v++)
if (!spt[v] && amtrx[u][v] != INF && dist[u] != INF && dist[u] + amtrx[u][v] < dist[v])
dist[v] = dist[u] + amtrx[u][v];
}
printpaths(dist, n);
}
Output now:
0 1 INF (no path)
0 2 INF (no path)
0 3 INF (no path)
0 4 INF (no path)
0 5 INF (no path)
update 2
void dijkstras(int amtrx[][N], int n) {
int min = INF, dist[N], count, v, u;
bool spt[N];
for (v = 0; v < N; v++) {
dist[v] = INF;
spt[v] = false;
}
dist[src] = 0;
for (count = 0; count < N - 1; count++) {
for (v = 0; v < N; v++)
if (spt[v] == false && dist[v] <= min)
min = dist[v], u = v;
spt[u] = true;
for (v = 0; v < N; v++)
if (!spt[v] && amtrx[u][v] && dist[u] != INF && dist[u] + amtrx[u][v] < dist[v])
dist[v] = dist[u] + amtrx[u][v];
}
printpaths(dist, n);
}
output:
0 1 50
0 2 10
0 3 INF (no path)
0 4 45
0 5 INF (no path)
I'm so close I can taste it! Any help is appreciated!

void dijkstras(int amtrx[][N], int n) {
int min = INF, dist[n], count, v, u;
bool spt[n];
for (v = 0; v < n; v++) {
dist[v] = INF;
spt[v] = false;
}
dist[src] = 0;
for (count = 0; count < n - 1; count++) {
min=INF;
for (v = 0; v < n; v++)
if (spt[v] == false && dist[v] <= min)
min = dist[v], u = v;
spt[u] = true;
for (v = 0; v < n; v++)
if (!spt[v] && amtrx[u][v] != INF && dist[u] != INF && dist[u] + amtrx[u][v] < dist[v])
dist[v] = dist[u] + amtrx[u][v];
}
printpaths(dist, n);
}

Related

Shortest path with Bellman & Ford algorithm

I want to implement Shortest path with Bellman & Ford algorithm. my idea is I use adjacent matrix
to save the information of digraph. If I want to find the shorest path of vertex i ,then I observe in-
degree of vertex i by the ith column of adjacent matrix ,and I save the shortest value of ith column
to a variable "min".if I want to find the shorest path from source vertex v to vertex i.
I only compare distance[i] with (distance[j]+ min ), because "min" is equal to adjmatrix[j][i].
In addition, I make the traverse(source, k) function to comfirm which vertex we can reach it in k
steps and use the data structure stack to save information of vertex i. I assume to that i'll get all the
shortest path from source vertex v to every vertex o graph except v itself. But the consequence after
compiling isn't that I expected. I finally got distance[i], 0 <= i < MAX_VERTEX, 1000,-1, 5, 5, 0 ,1000,
1000, respectively. What is my problem? Thanks for answer.
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX 7
#define FALSE 0
#define TRUE 1
#define MAX_DISTANCE_LIMIT 1000
#define MAX_STACK_LENGTH 100
#define MIN(x, y) ((x) < (y) ? x : y)
int stack[MAX_STACK_LENGTH];
int top = -1; //pointer to top of stack.
int adjmatrix[MAX_VERTEX][MAX_VERTEX];
short found[MAX_VERTEX]; //traverse(v ,k) : reach the vertex i By taking the k steps at most
int distance[MAX_VERTEX]; //save the shortest path that source v to every vertex i
int init_matrix(void);
void BellmanFord(int v); //v is source
void traverse(int v,int times);
void push(int vertex);
int pop(void);
int main(void){
int i,j;
init_matrix(); //initial matrix and found[] array
for(i = 0; i < MAX_VERTEX; i++){
for(j = 0; j < MAX_VERTEX; j++)
printf("%2d ", adjmatrix[i][j]);
printf("\n");
}
printf("--------------------------------------------------\n");
BellmanFord(0);
for(i = 0; i < MAX_VERTEX; i++)
printf("%4d ", i);
printf("\n");
for(i = 0; i < MAX_VERTEX; i++)
printf("%4d ", distance[i]);
return 0;
}
int init_matrix(void){
int num_edge = 0, i, j, w;
for(i = 0; i < MAX_VERTEX; i++){
found[i] = FALSE;
for(j = 0; j < MAX_VERTEX; j++)
adjmatrix[i][j] = MAX_DISTANCE_LIMIT; //set a large value to the entry of the vertice which aren't adjacent
}
while(1){
printf("enter the vertices and weight of edge connected between them(w,tail,head): ");
scanf("%d%d%d", &w, &i, &j);
if((i >= MAX_VERTEX) || (j >= MAX_VERTEX)){
fprintf(stderr, "index if the matrix should be less than %d");
exit(EXIT_FAILURE);
}
if(w == 0) break;
adjmatrix[i][j] = w;
num_edge++;
}
return num_edge;
}
void BellmanFord(int v){//compute all shortest path from v to every vertex ,and allow edge is negative
int i, k, min = MAX_DISTANCE_LIMIT, j, minpos;
for(int i = 0; i < MAX_VERTEX; i++)
distance[i] = adjmatrix[v][i]; //value of dist"1"
for(k = 2; k <= MAX_VERTEX - 1; k++){
traverse(v,k); //traverse(v ,k)will set found[i] that we can reach in k steps TRUE.
for(i = 0; i < MAX_VERTEX; i++ ){
if( found[i] == FALSE)
continue;
for(j = 0; j < MAX_VERTEX; j++)
if(adjmatrix[j][i]+distance[j] < min) {
min = adjmatrix[j][i]+distance[j];
minpos = j;
}
distance[i] = MIN(distance[i],adjmatrix[minpos][i]+distance[j]);
}
for(i = 0; i < MAX_VERTEX; i++ ) //initial found array to FALSE
found[i] = FALSE;
}
}
void traverse(int v,int times){
int i, next_order ,count = 0;
if (times == 0) return ;
for(i = 0; i < MAX_VERTEX; i++){
if((adjmatrix[v][i] != MAX_DISTANCE_LIMIT) && (!found[i])){
found[i] = TRUE;
if(times == 1)
return;
push(i);
count++;
}
}
for(i = 0; i < count; i++){
next_order = pop();
traverse(next_order,times-1);
}
return;
}
void push(int vertex){
if(top >= MAX_STACK_LENGTH){
fprintf(stderr, "The stack is full.");
exit(EXIT_FAILURE);
}
stack[++top] = vertex;
}
int pop(void){
if(top == -1){
fprintf(stderr, "The stack is empty.\n");
exit(EXIT_FAILURE);
}
else
return stack[top--];
}
/************************************
*graph information (w,tail,head)
input
6 0 1
5 0 2
5 0 3
-1 1 4
1 2 4
-2 2 1
-2 3 2
-1 3 5
3 5 6
3 4 6
0 0 0 //end the input
************************************
adjmatrix:
0 6 5 5 0 0 0
0 0 0 0 -1 0 0
0 -2 0 0 1 0 0
0 0 -2 0 0 -1 0
0 0 0 0 0 0 3
0 0 0 0 0 0 3
0 0 0 0 0 0 0
**************************************/

How to find and save parallel shortest path in undirected graph by Dijkstra’s algorithm in C

I have the follow graph:
A-B,11
A-C,10
B-D,5
C-D,6
C-E,15
D-E,4
The task is to find shortest path, print route and distance to all pairs like this:
Path: A -> D
Route: A -> C -> D
Distance: 10 + 6 = 16
In that example of graph, we have few path that repeating, but have a various route, like this:
Route: A -> B -> D
Route: A -> C -> D
I need to save all of this various path and print at the end. Now program find and print all path exept these cases. I tried many options, but for some reason I can’t understand how to solve this problem.
I store weights in 2 dimentional array like this:
A B C D E
A 0 11 10 0 0
B 11 0 0 5 0
C 10 0 0 6 15
D 0 5 6 0 4
E 0 0 15 4 0
My code below:
...
typedef struct s_way_dijkstra {
int isld_nm;
bool is_chk;
int parent;
struct s_way_dijkstra *next;
}t_way_dijkstra;
void printDistance(t_way_dijkstra *djk_var, int j) {
if (djk_var[j].parent == -1 )
return;
printDistance(djk_var, djk_var[j].parent);
if (djk_var[j].parent != 0 )
printstr("+ ");
printint(djk_var[j].isld_nm - djk_var[djk_var[j].parent].isld_nm);
printstr(" ");
// for (;i > 0 && djk_var->parent[i] != -1; i--)
// printf("%d ", j);
}
void printRoute(t_way_dijkstra *djk_var, int j, char **isld) {
if (djk_var[j].parent == -1)
return;
printRoute(djk_var, djk_var[j].parent, isld);
printstr(" -> ");
printstr(isld[j]);
}
static void printSolution(t_way_dijkstra *djk_var, int n, char **isld, int src) {
for (int i = 0; i < n; i++)
printf("%d ", djk_var[i].isld_nm);
printf("\n");
printf("\nparent\n");
for (int i = 0; i < n; i++)
printf("%d ", djk_var[i].parent);
printf("\n");
for (int i = src; i < n; i++) {
if (djk_var[i].isld_nm != 0) {
// Path
printstr("Path: ");
printstr(isld[src]);
printstr(" -> ");
printstr(isld[i]);
// Route
printstr("\nRoute: ");
printstr(isld[src]);
printRoute(djk_var, i, isld);
printstr("\n");
// Distance
if (djk_var[i].parent >= 1) {
printstr("Distance: ");
printDistance(djk_var, i);
printstr("= ");
printint(djk_var[i].isld_nm);
printstr("\n");
}
else {
printstr("Distance: ");
printint(djk_var[i].isld_nm);
printstr("\n");
}
}
}
}
static int get_min_distance(t_way_dijkstra *djk_var , t_main *vars) {
int min_val = INT_MAX;
int min_ind = 0;
for (int i = 0; i < vars->nmb_isld; i++) {
if (djk_var[i].is_chk == false && djk_var[i].isld_nm <= min_val) {
min_val = djk_var[i].isld_nm;
min_ind = i;
}
}
return min_ind;
}
static void dijkstra(int src, t_main *vars, t_graph *graph, t_way_dijkstra *djk_var) {
int min_ind = 0;
for (int i = 0; i < vars->nmb_isld; i++) {
djk_var[i].parent = -1;
djk_var[i].isld_nm = INT_MAX;
djk_var[i].is_chk = false;
}
djk_var[src].isld_nm = 0;
for (int i = 0; i < vars->nmb_isld; i++) {
min_ind = get_min_distance(djk_var, vars);
djk_var[min_ind].is_chk = true;
for (int j = src; j < vars->nmb_isld; j++) {
if (!djk_var[j].is_chk && graph->array[min_ind][j]
&& djk_var[min_ind].isld_nm != INT_MAX
&& djk_var[min_ind].isld_nm + graph->array[min_ind][j] < djk_var[j].isld_nm) {
djk_var[j].parent = min_ind;
djk_var[j].isld_nm = djk_var[min_ind].isld_nm + graph->array[min_ind][j];
}
}
}
printSolution(djk_var, vars->nmb_isld, graph->isld, src);
}
...

Fill 2d array in spiral order in c

I'm doing program where I enter the number from keyboard. Then 2d array is created, and it's filled in spiral order till this number. All elements after the number will be equal to 0; The function fills the array in spiral order (to right -> down -> left -> up).
Code is:
#include <stdio.h>
#include <time.h>
void spiral(int array[100][100], int m, int n, int s)
{
int size, b, x = 0, y = 1, num = 1;
size = m*n;
for (num=1;num<=size+1;num++)
{
for (b = x; b < n; b++)
{
if (num <=s) {
array[x][b] = num;
num++;
}
else array[x][b] = 0;
}
if (num == size + 1)
{
break;
}
for (b = y; b < m; b++)
{
if (num <=s) {
array[b][n - 1] = num;
num++;
}
else array[b][n - 1] = 0;
}
if (num == size + 1)
{
break;
}
y++;
n--;
for (b = n - 1; b > x; b--)
{
if (num <= s) {
array[m - 1][b] = num;
num++;
}
else array[m - 1][b] = 0;
}
if (num == size + 1)
{
break;
}
for (b = m - 1; b > x; b--)
{
if (num <= s) {
array[b][x] = num;
num++;
}
else array[b][x] = 0;
}
x++;
m--;
}
}
int main()
{
int m, n, s, array[100][100];
srand(time(NULL));
//m=3;
// n=4;
m = 2 + rand() % 5;
n = 2 + rand() % 5;
//memset(array, 0, sizeof(array[0][0]) * 10 * 10);
printf("enter the number \n");
scanf("%i", &s);
spiral(array, m, n, s);
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
printf("%i\t", array[i][j]);
}
printf("\n");
}
return (0); }
However it doesn't work always correctly.
For example when i enter 15 and the program generates 4*3 array the output is`
1 2 3
10 12 4
9 -858993460 5
8 7 6`
However expected output is
1 2 3
10 11 4
9 12 5
8 7 6
Or when i enter 15 and the program generates 4*5 array the output is
1 2 3 4 5
14 0 0 0 6
13 0 0 0 7
12 11 10 9 8
And the expected output is
1 2 3 4 5
14 15 0 0 6
13 0 0 0 7
12 11 10 9 8
I can't find whats wrong with this code.
Try this:
void printArray(int array[10][10], int m, int n) {
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
printf("%i\t", array[i][j]);
}
printf("\n");
}
printf("\n");
}
void spiral(int array[10][10], int m, int n, int s)
{
int size, b, x = 0, y = 1, num = 1;
size = m*n;
while ( num <= s )
{
for (b = x; b < n; b++)
{
if (num <= s) {
array[x][b] = num;
num++;
} else array[x][b] = 0;
}
if (num == size + 1)
{
break;
}
for (b = y; b < m; b++)
{
if (num <= s) {
array[b][n - 1] = num;
num++;
} else array[b][n - 1] = 0;
}
if (num == size + 1)
{
break;
}
y++;
n--;
for (b = n - 1; b > x; b--)
{
if (num <= s) {
array[m - 1][b] = num;
num++;
} else array[m - 1][b] = 0;
}
if (num == size + 1)
{
break;
}
for (b = m - 1; b > x; b--)
{
if (num <= s) {
array[b][x] = num;
num++;
} else array[b][x] = 0;
}
x++;
m--;
}
}
int main()
{
int m, n, s, array[10][10];
srand(time(NULL));
m = 2 + rand() % 5;
n = 2 + rand() % 5;
memset(array, 0, sizeof(array[0][0]) * 10* 10);
printf("enter the number \n");
scanf("%i", &s);
spiral(array, m, n, s);
printArray(array, m, n);
return (0);
}
Before you had some weird for loop on top of your spiral function. The num++ in it interfered with the fact that you already increased num by one and made it skip the number the next time it would write in the uppermost line.
I changed it to a while loop that runs until num>s and it seems to work for me now.
Note that I just added printArray for easier debugging.

Unclear Segmentation Fault returning 139 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I try to write a sudoku solver
I always get a segmentation fault after calling getPossibleElements in solveSudoku.
If I delete this line the error doesnt appear.
My Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SUDOKU_X 8
#define SUDOKU_Y 8
#define MAX_FILENAME 50
#define MAX_POSSIBILITIES 8
typedef enum bool {false, true} bool;
void printPossibilities (bool numbers[], const int pos_x, const int pos_y) {
int i = 0;
for (i = 0; i <= MAX_POSSIBILITIES; i++) {
if (numbers[i]) {
printf("%d ", (i+1));
}
}
}
void getPossibleElements (bool numbers[],int a[][SUDOKU_Y], const int pos_x, const int pos_y) {
int x = 0;
int y = 0;
int i = 0;
int j = 0;
int tmp = 0;
for (x = 0; x <= MAX_POSSIBILITIES; x++) {
numbers[x] = true;
}
/* row */
for (x = 0; x <= SUDOKU_X; x++) {
if (a[pos_y][x] > 0) {
printf("ROW->a[%d][%d]\n",pos_y,x);
printf("ROW->%d\n",a[pos_y][x]-1);
numbers[a[pos_y][x]-1] = false;
}
}
/* coloumn */
for (y = 0; y <= SUDOKU_Y; y++) {
if (a[y][pos_x] > 0) {
printf("coloumn->a[%d][%d]\n",y,pos_x);
printf("coloumn->%d\n",a[y][pos_x]-1);
numbers[a[y][pos_x]-1] = false;
}
}
/* field */
if (pos_x <= 2 && pos_y <= 2) {
x = 0;
y = 0;
}
else if (pos_x <= 5 && pos_y <= 2) {
x = 3;
y = 0;
}
else if (pos_x <= 8 && pos_y <= 2) {
x = 6;
y = 0;
}
else if (pos_x <= 2 && pos_y <= 5) {
x = 0;
y = 3;
}
else if (pos_x <= 5 && pos_y <= 5) {
x = 3;
y = 3;
}
else if (pos_x <= 8 && pos_y <= 5) {
x = 6;
y = 3;
}
else if (pos_x <= 2) {
x = 0;
y = 6;
}
else if (pos_x <= 5) {
x = 3;
y = 6;
}
else if (pos_x <= 8) {
x = 6;
y = 6;
}
printf("DB!!! x=%d y=%d\n", x,y);
for (j = y; j < (y+3); j++) {
for (i = x; i < (x+3); i++) {
if (a[j][i] > 0) {
printf("FIELD->a[%d][%d]\n",j,i);
printf("FIELD->%d\n",(a[j][i])-1);
numbers[(a[j][i])-1] = false;
}
}
}
printf("db");
}
void printSudoku (int a[][SUDOKU_Y]) {
int i = 0;
int j = 0;
printf("-------------------------------\n");
for (j = 0; j <= SUDOKU_X; j++)
{
for (i = 0; i <= SUDOKU_Y; i++) {
if (i == 0) {
printf("|");
}
printf(" %d ",a[j][i]);
if (i == 2 || i == 5 || i == 8) {
printf("|");
}
}
printf("\n");
if (j == 2 || j == 5) {
printf("|-----------------------------|\n");
}
}
printf("-------------------------------\n");
}/* printSudoku */
bool solveSudoku (int a [][SUDOKU_Y]) {
bool numbers[MAX_POSSIBILITIES];
int x = 0;
int y = 0;
printSudoku(a);
getPossibleElements(numbers,a,x,y);
printPossibilities(numbers,x,y);
return true;
}
void readFiletoArray (const char * fileName, int a[][SUDOKU_Y])
{
FILE *fp = fopen(fileName,"r");
int i = 0;
int j = 0;
int val0 = 0;
int val1 = 0;
int val2 = 0;
if( fp == NULL ) {
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
while(fscanf(fp, "%d %d %d", &val0, &val1, &val2) > 0) {
a[j][i++] = val0;
a[j][i++] = val1;
a[j][i++] = val2;
if (i >= 8) {
i = 0;
j++;
}
}
fclose(fp);
} /* readFiletoArray */
int main (int argc, char * argv []) {
int a[SUDOKU_X][SUDOKU_Y];
char fileName[MAX_FILENAME];
bool numbers[MAX_POSSIBILITIES];
bool success = false;
if(argc == 2) {
strncpy(fileName, argv[1], MAX_FILENAME-1);
fileName[MAX_FILENAME] = '\0';
}
else {
printf("ERROR: Invalid Parameter\n");
exit(EXIT_FAILURE);
}
readFiletoArray(fileName, a);
success = solveSudoku(a);
printf("DB");
exit(EXIT_SUCCESS);
} /* Main */
sudoku.txt (Program Parameter)
0 5 9 0 4 0 2 0 0
0 1 0 0 5 0 0 0 7
4 0 0 3 2 9 0 1 5
3 2 0 1 0 0 9 0 0
0 0 7 4 0 6 5 0 0
0 0 4 0 0 5 0 7 8
6 9 0 5 0 3 0 0 4
5 0 0 0 6 0 0 3 0
0 0 8 0 1 0 6 5 0
Thx
At a glance, this is because you are running off the end of the array in various places.
for (x = 0; x <= MAX_POSSIBILITIES; x++) { // 0,1,2...8
See that <= you have there? That's your problem.
numbers is declared as bool numbers[MAX_POSSIBILITIES];, and array indices in C start at 0 and go to length - 1. Zero through seven in this case, but you are trying to access numbers[8].
You have the same issue elsewhere. a is declared as
int a[SUDOKU_X][SUDOKU_Y]; // int a[8][8];
and in getPossibleElements you are iterating from 0 to 8 inclusive, like so:
for (x = 0; x <= SUDOKU_X; x++) {
...
for (y = 0; y <= SUDOKU_Y; y++) {
...thus running off the end of your array again.
Same deal in printPossibilities.
Change MAX_POSSIBILITIES, SUDOKU_X and SUDOKU_Y to be 9 in your #defines and iterate from 0 to 8 by doing
for (x = 0; x < SUDOKU_X; x++) { // 0,1,2...8
One more thing. You should fix your fileName stuff too. Same deal. The last index in an array is length - 1, not length. If you had warnings cranked up when you compiled, it probably would have mentioned this one.
if (argc == 2) {
strncpy(fileName, argv[1], MAX_FILENAME - 2); // was MAX_FILENAME - 1
fileName[MAX_FILENAME - 1] = '\0'; // was [MAX_FILENAME]
}

how to build spiral square matrix using recursion?

I wanted to build a spiral square matrix using recursion. I am able to build spiral square matrix using iterative method as below:
void main()
{
int initial_direction = UP , n = MAX , p = 1 ; /* intial_direction
is set to UP because we need to start moving right */
int r ,c , a[MAX][MAX];
int row_right = 0 , column_down = n-1 , row_left = n-1 , column_up = 0 ;
clrscr ();
//Set all elements of the matrix to 0
for(r = 0 ; r < MAX ; r++)
{
for(c = 0 ; c < MAX ; c++)
a[r][c] = 0 ;
}
//Generate elements of the spiral matrix
while(p != n*n+1)
{
if(initial_direction == UP)
{
//Move RIGHT
r = row_right++ ;
for(c = 0 ; c < n ; c++)
{
if(a[r][c] == 0)
a[r][c] = p++;
}
initial_direction = RIGHT ;
}
else if(initial_direction == RIGHT)
{
//Move down
c = column_down-- ;
for(r = 0 ; r < n ; r++)
{
if(a[r][c] == 0)
a[r][c] = p++;
}
initial_direction = DOWN ;
}
else if(initial_direction == DOWN)
{
//Move left
r = row_left-- ;
for(c = n-1 ; c >= 0 ; c--)
{
if(a[r][c] == 0)
a[r][c] = p++;
}
initial_direction = LEFT ;
}
else if(initial_direction == LEFT)
{
//Move up
c = column_up++;
for(r = n-1 ; r >= 0 ; r--)
{
if(a[r][c] == 0)
a[r][c] = p++;
}
initial_direction = UP ;
}
}
//Print the matrix
printf("\n\n");
for(r = 0 ; r < MAX ; r++)
{
for(c = 0 ; c < MAX ; c++)
printf("%4d ",a[r][c]);
printf("\n");
}
}
I wanted to create the same matrix using recursion:
Here is the code i used:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
bool s[5][5] = {0};
int counter;
typedef enum {
right = 0,
down,
left,
up
}c_flag;
c_flag flag;
int last;
int build_matrix(int a[5][5],int i,int j, c_flag flag)
{
int ret;
if (i < 0 || i>=5 || j < 0 || j >= 5)
{
if (last == right)
{
flag = down;
last = flag;
}
if (last == down)
{
flag = left;
last = flag;
}
if (last == left)
{
flag = up;
last = flag;
}
if (last == up)
{
flag = left;
last = flag;
}
return false;
}
if (s[i][j] == true)
{
if (last == right)
{
flag = down;
last = flag;
}
if (last == down)
{
flag = left;
last = flag;
}
if (last == left)
{
flag = up;
last = flag;
}
if (last == up)
{
flag = left;
last = flag;
}
return false;
}
if(s[i][j] == false)
{
s[i][j] = true;
a[i][j] = ++ counter;
}
if (flag == right)
{
ret = build_matrix(a,i,j+1,right);
//if (!ret)
// return false;
}
flag = down;
last = flag;
if (flag == down)
{
ret =build_matrix(a,i+1,j,down);
//if (!ret)
// return false;
}
flag = left;
last = flag;
if (flag == left)
{
ret = build_matrix(a,i,j-1,left);
//if (!ret)
// return false;
}
flag = up;
last = flag;
if (flag == up)
{
ret = build_matrix (a,i-1,j,up);
//if (!ret)
// return false;
}
flag = right;
last = flag;
return false;
}
int main()
{
int i, j, n = 5;
int k, ret;
//printf("Enter N to construct square matrix \n");
//scanf("%d",&n);
int a[5][5] = {0};
k = n/2 + n%2;
for (i = 0; i < k; i++)
{
ret = build_matrix(a,i,i,right);
}
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
printf("%d",a[i][j]);
printf("\n");
}
return 0;
}
I am getting out put for above as :
1 2 3 4 5
16 19 22 25 6
15 18 21 24 7
14 17 20 23 8
13 12 11 10 9
instead of
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Problem is Flag is not setting proper, i dunno inside which recursion call flag is getting disturbed.
Please some one help implement using recursion.
#include <stdio.h>
void build_matrix(int msize, int a[msize][msize], int size, int value){
int i, row, col;
if(size < 1)
return;
row = col = (msize - size) / 2;
if(size==1){
a[row][col] = value;
return;
}
for(i=0;i<size-1;++i)
a[row][col++] = value++;//RIGHT
for(i=0;i<size-1;++i)
a[row++][col] = value++;//DOWN
for(i=0;i<size-1;++i)
a[row][col--] = value++;//LEFT
for(i=0;i<size-1;++i)
a[row--][col] = value++;//UP
build_matrix(msize, a, size-2, value);
}
int main(){
int size;
printf("input size : ");
scanf("%d", &size);
int a[size][size];
build_matrix(size, a, size, 1);
for(int r=0;r<size;++r){
for(int c=0;c<size;++c)
printf("%3d ", a[r][c]);
printf("\n");
}
return 0;
}
Working Code, without divide and Just recurse:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define N 20
bool s[N][N] = {0};
int counter;
typedef enum {
right = 0,
down,
left,
up
}c_flag;
c_flag flag;
int build_matrix(int a[N][N],int i,int j, c_flag flag)
{
int ret;
if (i < 0 || i>=N || j < 0 || j >= N || s[i][j] == true)
return false;
if(s[i][j] == false && a[i][j] == 0)
{
s[i][j] = true;
a[i][j] = ++ counter;
}
if (flag == right)
ret = build_matrix(a,i,j+1,right);
flag = down;
if (flag == down)
ret =build_matrix(a,i+1,j,down);
flag = left;
if (flag == left)
ret = build_matrix(a,i,j-1,left);
flag = up;
if (flag == up)
ret = build_matrix (a,i-1,j,up);
flag = right;
if (flag == right)
ret = build_matrix(a,i,j+1,right);
return false;
}
int main()
{
int i, j;
int k, ret;
//printf("Enter N to construct square matrix \n");
//scanf("%d",&n);
int a[N][N] = {0};
k = N/2 + N%2;
build_matrix(a,i,i,right);
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
if (!(a[i][j] < 100))
printf("%3d ",a[i][j]);
else if(a[i][j] < 10)
printf("00%d ",a[i][j]);
else
printf("0%d ",a[i][j]);
}
printf("\n");
}
return 0;
}

Resources