Recursion find all paths in graph matrix DFS - c

I'm trying to implement a two functions based on Depth First Search using a recursion method. I'm ultimately trying to compare the runtime against warshall's algorithm (which I already have working). When I print my matrix it's off by a couple off paths.
The recursion is what may be throwing me off, it's my weakness. Because of the top if statement if(iIndex1 == iIndex2) return TRUE;, when I try to find if there is a path from (A,A), (B,B), (C,C), etc. I will always get 1 even if there is no path from A to A.
typedef enum { FALSE, TRUE } bool;
/* Recursive function will determine if there is a path from index 1 to 2
* Based of DFS
*/
bool recPathExists( Graph G, int iIndex1, int iIndex2 )
{
int j;
G.nodeArray[iIndex1].visited = TRUE;
if(iIndex1 == iIndex2){
return TRUE;
}
for(j = 0; j < G.iNumNodes; j++){
if(!G.nodeArray[j].visited && G.adjMatrix[iIndex1][j]==1){
if(recPathExists(G, j, iIndex2))
return TRUE;
}
}
return FALSE;
}
/* Write a function to find all pairs of nodes which have paths between them.
* Store this information in the provided pathMatrix.
*/
void allPathsRecFunc( Graph G , int **pathMatrix )
{
int i, j;
for(i = 0; i < G.iNumNodes; i++){
for(j = 0; j < G.iNumNodes; j++){
if(recPathExists(G, i , j)== TRUE){
pathMatrix[i][j] = 1;
}
resetVisited(G); //resets all nodes to FALSE
}
}
}
what it should be
A 0 1 1 1 1 1 1 1
B 0 1 0 0 1 1 1 1
C 0 1 0 0 1 1 1 1
D 0 0 0 0 0 0 0 0
E 0 0 0 0 0 0 0 0
F 0 1 0 0 1 1 1 1
G 0 1 0 0 1 1 1 1
H 0 1 0 0 1 1 1 1
what I get
A 1 1 1 1 1 1 1 1
B 0 1 0 0 1 1 1 1
C 0 1 1 0 1 1 1 1
D 0 0 0 1 0 0 0 0
E 0 0 0 0 1 0 0 0
F 0 1 0 0 1 1 1 1
G 0 1 0 0 1 1 1 1
H 0 1 0 0 1 1 1 1

Your issue may be here:
for(j = 0; j < G.iNumNodes; j++)
{
if(!G.nodeArray[j].visited && G.adjMatrix[iIndex1][j] == 1)
{
return recPathExists(G, j, iIndex2);
}
}
By returning the result of recursing on recPathExists, you're not checking the other possible nodes that could be reachable in the loop (in essence, you're returning failure too early, and missing possible paths).
I believe you want just a little modification:
for(j = 0; j < G.iNumNodes; j++)
{
if(!G.nodeArray[j].visited && G.adjMatrix[iIndex1][j] == 1)
{
if (recPathExists(G, j, iIndex2))
return TRUE;
}
}
That is, "if a path does exist, return as we've found it. If not, keep looking".

My depth first search uses recursion but it outputs a parent array, though the functionality should be the same. It got a perfect grade so I know it works. Hope it helps.
https://github.com/grantSwalwell/Data-Structures/blob/master/Depth%20First%20Search.h
Algorithm~
bool array, visited for flagging nodes
search number array to measure the depth of access
depth to increment and come up with search num
Call DFS on 0,0
For each non visited neighbor
DFS depth + 1, search = depth, visited = true
return parent array, showing the search pattern
// Depth First Search recursive helper method
void DFS(Graph& G, int v0, Array<bool>* visited, Array<int>* search, int
depth)
{
// set visited
(*visited)[v0] = true;
// set search num
(*search)[v0] = depth;
// iterate through neighbors
for (int i = 0; i < G.nodes(); i++)
{
// if i is a neighbor
if (G.edge(i, v0))
{
// if it has not been visited
if (!(*visited)[i])
{
// call DFS
DFS(G, i, visited, search, depth + 1);
}
} // end if
} // end for
}
// Depth First Search
Array<int>* DFS(Graph& G, int v0)
{
// visited array
Array<bool>* visited = new Array<bool>(G.nodes());
// search number array, order of visitation
Array<int>* search = new Array<int>(G.nodes());
// initialize both arrays
for (int i = 0; i < G.nodes(); i++)
{
(*visited)[i] = false;
(*search)[i] = 1;
}
// create depth field
int depth = 1;
// call DFS
DFS(G, v0, visited, search, depth);
return search;
};

Related

How do I use a switch to offset the start of a for loop?

I am trying to make a game of checkers, and right now I'm building the board. The board is a 2-dimensional array of integers that I'm changing based on where the pieces should be.
// Sets up Red Pieces
int k = 0;
for (i = 0; i < 3; i++)
{
for (j = k; j < 8; j += 2)
{
// Red piece is on square at coords [i][j]
Board_Squares[i][j] += 2;
}
printf("\n");
// k starts at 0, and in switch should alternate between 1 and 0,
switch (k)
{
case 0:
k = 1;
case 1:
k = 0;
}
}
However, this code only gives me this:
0 2 0 2 0 2 0
0 2 0 2 0 2 0
0 2 0 2 0 2 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
Any help would be dope. Warning: I might be dumb.
Also, is using the switch statement the right move here anyways?
the problem in your code comes from missing break statements: the code for a case fall through to the code for the next case.
Modify it this way:
switch (k) {
case 0:
k = 1;
break;
case 1:
k = 0;
break;
}
The same toggling effect can be obtained with simple expressions:
k = 1 - k;
k ^= 1;
k = !k;
k = k == 0;
Or some more convoluted and obscure ones:
k = !!!k;
k = k ? 0 : 1;
k = (k + 1) & 1;
k = "\1"[k];
k = k["\1"];
k = 1 / (1 + k);
The checker board cells can also be initialized directly to 0 and 1 as:
Board_Squares[i][j] = (i + j) & 1;

Implementing 8-Connectivity Hoshen-Kopelman Algorithm in C

I found here an implementation for Hoshen-Kopelman Algorithm, But it checks neighbors only up and left, meaning that a diagonal connection is not considered a connection.
How can I improve this code so that even a diagonal connection will be considered a connection?
In the following example I expect 1 object and not 7 objects:
4 5
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--input--
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--output--
1 0 2 0 3
0 4 0 5 0
6 0 7 0 0
0 0 7 0 0
HK reports 7 clusters found
This is the implementation (full code can be found here):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* Implementation of Union-Find Algorithm */
/* The 'labels' array has the meaning that labels[x] is an alias for the label x; by
following this chain until x == labels[x], you can find the canonical name of an
equivalence class. The labels start at one; labels[0] is a special value indicating
the highest label already used. */
int* labels;
int n_labels = 0; /* length of the labels array */
/* uf_find returns the canonical label for the equivalence class containing x */
int uf_find(int x)
{
int y = x;
while (labels[y] != y)
y = labels[y];
while (labels[x] != x)
{
int z = labels[x];
labels[x] = y;
x = z;
}
return y;
}
/* uf_union joins two equivalence classes and returns the canonical label of the resulting class. */
int uf_union(int x, int y)
{
return labels[uf_find(x)] = uf_find(y);
}
/* uf_make_set creates a new equivalence class and returns its label */
int uf_make_set(void)
{
labels[0] ++;
assert(labels[0] < n_labels);
labels[labels[0]] = labels[0];
return labels[0];
}
/* uf_intitialize sets up the data structures needed by the union-find implementation. */
void uf_initialize(int max_labels)
{
n_labels = max_labels;
labels = calloc(sizeof(int), n_labels);
labels[0] = 0;
}
/* uf_done frees the memory used by the union-find data structures */
void uf_done(void)
{
n_labels = 0;
free(labels);
labels = 0;
}
/* End Union-Find implementation */
#define max(a,b) (a>b?a:b)
#define min(a,b) (a>b?b:a)
/* print_matrix prints out a matrix that is set up in the "pointer to pointers" scheme
(aka, an array of arrays); this is incompatible with C's usual representation of 2D
arrays, but allows for 2D arrays with dimensions determined at run-time */
void print_matrix(int** matrix, int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
printf("%3d ", matrix[i][j]);
printf("\n");
}
}
/* Label the clusters in "matrix". Return the total number of clusters found. */
int hoshen_kopelman(int** matrix, int m, int n)
{
uf_initialize(m * n / 2);
/* scan the matrix */
for (int y = 0; y < m; y++)
{
for (int x = 0; x < n; x++)
{
if (matrix[y][x])
{ // if occupied ...
int up = (y == 0 ? 0 : matrix[y - 1][x]); // look up
int left = (x == 0 ? 0 : matrix[y][x - 1]); // look left
switch (!!up + !!left)
{
case 0:
matrix[y][x] = uf_make_set(); // a new cluster
break;
case 1: // part of an existing cluster
matrix[y][x] = max(up, left); // whichever is nonzero is labelled
break;
case 2: // this site binds two clusters
matrix[y][x] = uf_union(up, left);
break;
}
}
}
}
/* apply the relabeling to the matrix */
/* This is a little bit sneaky.. we create a mapping from the canonical labels
determined by union/find into a new set of canonical labels, which are
guaranteed to be sequential. */
int* new_labels = calloc(sizeof(int), n_labels); // allocate array, initialized to zero
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (matrix[i][j])
{
int x = uf_find(matrix[i][j]);
if (new_labels[x] == 0)
{
new_labels[0]++;
new_labels[x] = new_labels[0];
}
matrix[i][j] = new_labels[x];
}
int total_clusters = new_labels[0];
free(new_labels);
uf_done();
return total_clusters;
}
/* This procedure checks to see that any occupied neighbors of an occupied site
have the same label. */
void check_labelling(int** matrix, int m, int n)
{
int N, S, E, W;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (matrix[i][j])
{
N = (i == 0 ? 0 : matrix[i - 1][j]);
S = (i == m - 1 ? 0 : matrix[i + 1][j]);
E = (j == n - 1 ? 0 : matrix[i][j + 1]);
W = (j == 0 ? 0 : matrix[i][j - 1]);
assert(N == 0 || matrix[i][j] == N);
assert(S == 0 || matrix[i][j] == S);
assert(E == 0 || matrix[i][j] == E);
assert(W == 0 || matrix[i][j] == W);
}
}
/* The sample program reads in a matrix from standard input, runs the HK algorithm on
it, and prints out the results. The form of the input is two integers giving the
dimensions of the matrix, followed by the matrix elements (with data separated by
whitespace).
a sample input file is the following:
8 8
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1
1 0 0 0 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 1 1 0 1
1 1 1 1 0 0 0 1
0 0 0 1 1 1 0 1
this sample input gives the following output:
--input--
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1
1 0 0 0 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 1 1 0 1
1 1 1 1 0 0 0 1
0 0 0 1 1 1 0 1
--output--
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1
2 0 0 0 0 2 0 1
2 0 0 2 0 2 0 1
2 0 0 2 0 2 0 1
2 0 0 2 2 2 0 1
2 2 2 2 0 0 0 1
0 0 0 2 2 2 0 1
HK reports 2 clusters found
*/
int main(int argc, char** argv)
{
int m, n;
int** matrix;
/* Read in the matrix from standard input
The whitespace-deliminated matrix input is preceeded
by the number of rows and number of columns */
while (2 == scanf_s("%d %d", &m, &n))
{ // m = rows, n = columns
matrix = (int**)calloc(m, sizeof(int*));
for (int i = 0; i < m; i++)
{
matrix[i] = (int*)calloc(n, sizeof(int));
for (int j = 0; j < n; j++)
scanf_s("%d", &(matrix[i][j]));
}
printf_s(" --input-- \n");
print_matrix(matrix, m, n);
printf(" --output-- \n");
/* Process the matrix */
int clusters = hoshen_kopelman(matrix, m, n);
/* Output the result */
print_matrix(matrix, m, n);
check_labelling(matrix, m, n);
printf("HK reports %d clusters found\n", clusters);
for (int i = 0; i < m; i++)
free(matrix[i]);
free(matrix);
}
return 0;
}
I tried to change the function hoshen_kopelman as described below, but I still get 2 objects instead of 1:
int hoshen_kopelman(int** matrix, int m, int n)
{
uf_initialize(m * n / 2);
/* scan the matrix */
for (int y = 0; y < m; y++)
{
for (int x = 0; x < n; x++)
{
if (matrix[y][x])
{ // if occupied ...
int up = (y == 0 ? 0 : matrix[y - 1][x]); // look up
int left = (x == 0 ? 0 : matrix[y][x - 1]); // look left
// ----------- THE NEW CODE -------------
if (x > 0)
{
if (up == 0 && y > 0) // left+up
up = matrix[y - 1][x - 1];
if (left == 0 && y < m - 1) // left+down
left = matrix[y + 1][x - 1];
}
// ---------- END NEW CODE --------------
switch (!!up + !!left)
{
case 0:
matrix[y][x] = uf_make_set(); // a new cluster
break;
case 1: // part of an existing cluster
matrix[y][x] = max(up, left); // whichever is nonzero is labelled
break;
case 2: // this site binds two clusters
matrix[y][x] = uf_union(up, left);
break;
}
}
}
}
/* apply the relabeling to the matrix */
/* This is a little bit sneaky.. we create a mapping from the canonical labels
determined by union/find into a new set of canonical labels, which are
guaranteed to be sequential. */
int* new_labels = calloc(sizeof(int), n_labels); // allocate array, initialized to zero
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (matrix[i][j])
{
int x = uf_find(matrix[i][j]);
if (new_labels[x] == 0)
{
new_labels[0]++;
new_labels[x] = new_labels[0];
}
matrix[i][j] = new_labels[x];
}
int total_clusters = new_labels[0];
free(new_labels);
uf_done();
return total_clusters;
}
The following output is now obtained (I am expecting 1 and got 2):
4 5
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--input--
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--output--
1 0 1 0 1
0 1 0 1 0
2 0 1 0 0
0 0 1 0 0
HK reports 2 clusters found
What is the correct way to correct the code to check all 8 neighbors?
I led you astray saying to check down-left. The algorithm relies on the current node it is examining being after all the neighbors it checks. So you need to check left, up, up-left, and up-right. You can use this in place of your new code:
if (y > 0)
{
if (left == 0 && x > 0) // left+up
left = matrix[y - 1][x - 1];
if (up == 0 && x < n-1) // right+up
up = matrix[y - 1][x + 1];
}

Move values down in a Matrix C

I'm still a noob at programming and still don't know many of the functions that I'm able to use so I kept to the basics, I was trying to create the game 2048 in C, for that I decided to make a function to push numbers in certain directions, either upwards, downwards, left or right. My up function is working, but my down function isn't even though I did the opposite of what I did in my up function. In the push_down function the numbers actually do what they do in the push_up functions, they move up instead of down.
Would love to know why it isn't working if anyone can spot my mistake
//this one is working
void push_up(int game_size, int grid[game_size][game_size])
{
int replace;
int num=0;
for (int j = 0; j < game_size ; ++j)
{
for (int i = 0; i < game_size ; ++i)
{
replace = 100;
if(grid[i][j]==0)
{
for (int a = game_size - 1 ; a > 0 + i ; --a)
{
if(grid[a][j]!=0)
{
num=grid[a][j];
replace=a;
}
}
grid[i][j]=num;
num=0;
}
if(replace!=100){
grid[replace][j]=0;
}
}
}
}
// this one isn't working
void push_down(int game_size, int grid[game_size][game_size])
{
int replace;
int num=0;
for (int j = 0; j < game_size ; ++j)
{
for (int i = game_size - 1; i >= 0 ; --i)
{
replace = 100;
if(grid[i][j]==0)
{
for (int a = 0 ; a < game_size - i ; ++a)
{
if(grid[a][j]!=0)
{
num=grid[a][j];
replace=a;
}
}
grid[i][j]=num; //
num=0;
}
if(replace!=100){
grid[replace][j]=0;
}
}
}
}
What I did in both is mainly to run the column(either upwards or downwards depending on the function) trying to find a zero, lock the position of the zero and try to find the next number in that column by running the column in the opposite direction, the last number (if a number was even found) would be used to fill that zero and the position where the number was would be filled with 0.
So, let me give an example of what I wanted with these function:
In the first function (push_up) I wanted and was able to do a function that would transform this matrix :
4 2 4 0
0 0 0 0
0 4 2 2
2 0 4 2
into this one:
4 2 4 2
2 4 2 2
0 0 4 0
0 0 0 0
So, all the values would move to the highest position possible inside the column.
In the second function what I wanted was to transform this matrix:
4 2 4 0
0 0 0 0
0 4 2 2
2 0 4 2
into this one:
0 0 0 0
0 0 4 0
4 2 2 2
2 4 4 2
All the values would move to the lowest possible position inside the matrix. But I wasn't able to, by running the function what I get is:
This is the original matrix:
0 0 0 0
4 0 0 2
2 0 0 4
0 2 0 0
This is the matrix after using the function push_down:
2 2 0 4
4 0 0 2
0 0 0 0
0 0 0 0
There are probably easier ways to do this, I would love to hear them but I would also love to know where my logic went wrong in the push_down function since in the push_up function it's working fine.
Your example isn't reproducible and I'm not certain exactly what you're trying to do, but this is the obvious error:
for (int a = 0 ; a > game_size - i ; ++a)
{
if(grid[a][j]!=0)
{
num=grid[a][j];
replace=a;
}
}
This loop will never run, a is zero and will never be greater than game_size - 1.

2D array - I want to find which columns have 1s in them in each row

My input looks like this :
15 5
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
0 1 0 1 0
0 0 1 0 0
0 0 0 0 1
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
1 0 0 0 1
0 0 1 0 0
0 0 0 1 0
The first row contains the number of rows and columns of my array. And basically I want to find out where these 1s are in the array.
So in the first 3 rows i want to get 3, in the 7th 1, and in the 8th, i want to get 2 3 etc..
My code looks like this so far
#include <stdio.h>
int main() {
int row, column;
FILE* input;
FILE* output;
input = fopen("input.txt", "r");
if (input == 0) {
printf("ERROR couldn't open input.txt");
return 1;
}
if (! fscanf(input, "%d %d", &row, &column)) {
printf("ERROR not recognised value");
fclose(input);
return 2;
}
output = fopen("output.txt", "w");
int meteor[row][column];
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
fscanf(input, "%d", &meteor[i][j]);
}
}
int sum;
int loc[row];
for (int i = 0; i < row; i++) {
sum = 0;
for (int j = 0; j < column; j++) {
sum += meteor[i][j];
if (meteor[i][j] == 1) {
loc[i] = (j + 1);
}
}
printf("%d %d\n", loc[i], sum);
}
fclose(input);
fclose(output);
return 0;
}
My output is this :
3 1
3 1
3 1
0 0
-1 0
1 1
4 2
3 1
5 1
0 0
4214921 0
2 1
5 2
3 1
4 1
The first column shows some of the locations, the second shows how many 1s are in the row, but it all fails when there are only 0s in the row or there is more than one 1. And also I would like to store these values.
You need to initialize loc[].. If you look carefully at your code, you only populate it on the condition of if (meteor[i][j] == 1)... but you print it for every index of i. which would print uninitialized memory (i.e. unknown).
To answer the second part of your question, if you want to store the "sum". Simply make loc[] a 2d array just like meteor, but with 2 columns (row and sum). i.e. int loc[row][2].. making sure to initialize both columns of course :)

Minesweeper algorithm for finding neighbours?

Im programming in c the minesweeper game.
im pretty at the end.
I have only problem with the last part.
in the game (see picture) when I click on the upper left field, the fields where no mine is are turned around and at the border there are numbers.
how is the algorithm for finding this field and turn them around or to show them .... I mean algorithm for the field in the green circle?
I am doing a design from scratch, I hope it helps you.
If my game arena is nxn matrix of integers,
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
I can model placing a bomb in that matrix by applying such a 3x3 matrix:
1 1 1
1 9 1
1 1 1
Here 9 denotes a bomb, you probably need to use a bigger integer. And when I say apply, I pick the location and increment it by the numbers in that 3x3 matrix. So let's place 1 bomb:
0 1 1 1 0
0 1 9 1 0
0 1 1 1 0
0 0 0 0 0
0 0 0 0 0
Let's place another bomb, just next to the first one. And let's be a bit clever and not increment the location when the initial value in a cell is 9.
0 1 2 2 1
0 1 9 9 1
0 1 2 2 1
0 0 0 0 0
0 0 0 0 0
Let's place another one this time somewhere below.
0 1 2 2 1
0 1 9 9 1
0 1 3 3 2
0 0 1 9 1
0 0 1 1 1
So if I try to start revealing numbers from bottom right. What should be my algorithm? Here is my take:
function revealCell(location)
{
if(cellValueIsRevealed(location)) {
return;
}
var value = revealValueOfCell(location);
if(value > 0)
{
return;
}
foreach(neighbor in neighbors)
{
revealCell(neighbor);
}
}
To implement cellValueIsRevealed method, one way would be to implement a matrix of booleans.
Might be a little late to answer the question, but I'll do it anyway so that if someone sees this in the future it might help them out. This is also written in C# but the general idea should be the same.
The idea is to have a Queue of cells to visit, and a unique collection for visited cells. Start by queueing the current position and then evaluate the whole queue until it's empty. Dequeue the current cell and check if it's already visited. If it's not then check all the surrounding cells and enqueue them if they are empty cells. When you have finished the queue the hashset contains all the empty cells.
public void AsQueue(Queue<(int i, int j)> toVisit, HashSet<(int i, int j)> visited, Cell[] grid, int i, int j)
{
List<(int i, int j)> neighbours = new();
toVisit.Enqueue((i, j));
while (toVisit.Count != 0)
{
var temp = toVisit.Dequeue();
if (!visited.Contains(temp))
{
Neighbours(neighbours, i, j, grid.GetLength(0), grid.GetLength(1));
for (int k = 0; k < neighbours.Count; k++)
{
if (grid[neighbours[k].i, neighbours[k].j].Type == BoxType.Empty &&
!(neighbours[k].i == i && neighbours[k].j == j) &&
!visited.Contains(neighbours[k]))
{
toVisit.Enqueue(neighbours[k]);
}
}
}
visited.Add(temp);
}
}
private void Neighbours(List<(int i, int j)> neighbours, int i, int j, int maxh, int maxw)
{
int[] iOffsets = new int[] { -1, 0, 1 }, jOffsets = new int[] { -1, 0, 1 };
if (i == 0) iOffsets = new int[] { 0, 1 };
else if (i == maxh - 1) iOffsets = new int[] { -1, 0 };
if (j == 0) jOffsets = new int[] { 0, 1 };
else if (j == maxw - 1) jOffsets = new int[] { -1, 0 };
neighbours.Clear();
foreach (var ip in iOffsets)
{
foreach (var jp in jOffsets)
{
neighbours.Add((i + ip, j + jp));
}
}
}

Resources