```/*  Description: Code printing valid tables for the game of flow.
Creator: Vaibhav Agarwal (vaiagarwal96@iitkgp.ac.in) */
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

struct _node
{
struct _node *parent;
int rank;
int path_number;
int endpoint;
};
typedef struct _node node;

/*    Name: initboard()
Input: 2D-array of pointers, size of array row/column
Output: --void--
Description: Takes a table of pointers and initializes it. */
void initboard(node ***arr, int n)
{
int i, j;
for (i=0;i<n;i++){
for (j=0;j<n;j++){
node *np;
np = (node *)malloc(sizeof(node));
np->rank = 0;
np->parent = NULL;
np->path_number = 0;
np->endpoint = 0;
arr[i][j] = np;
}
}
}
/***********************/

/*    Name: findset()
Input: a node
Output: the set pointer of the set the node belongs to
Description: Takes a node and returns the set pointer. */
node *findset(node *n)
{
if (n->parent != NULL)
n = n->parent;
return n;
}
/************************/

/*    Name: setunion()
Input: nodes x and y
Output: --void--
Description: merges the two sets containing x and y.
*/
void setunion(node *x, node *y)
{
x = findset(x);
y = findset(y);
if (x->rank > y->rank)
y->parent = x;
else{
x->parent = y;
if(x->rank == y->rank)
y->rank++;
}
}
/**************************/

/*    Name: neighbour()
Input: size of array row/column, 2D-array of pointers
Output: returns the incripted values of k1 and k2 or -1 if fails.
Description: Finds the valid starting points of the flow. */
int neighbour(int n, node ***arr)
{
int i1, i2, j1, j2, ct = 0, flag = 0, a, b,k2;
int k = rand()%(n*n);
while (ct < (n*n)){
k %= (n*n);
i1 = k/n;
j1 = k%n;

if (arr[i1][j1]->path_number==0)
{
int kk = rand()%4;
int cc = 0;
switch (kk)
{
case 0: i2= i1-1;
j2= j1-0;
if(i2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;

case 1:	i2= i1-0;
j2= j1-1;
if(j2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;

case 2: i2= i1+1;
j2= j1-0;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;

case 3: i2= i1-0;
j2= j1+1;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;

case 4: if(cc==4)
break;
i2= i1-1;
j2= j1-0;
if(i2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;

case 5: if(cc==4)
break;
i2= i1-0;
j2= j1-1;
if(j2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;

case 6: if(cc==4)
break;
i2= i1+1;
j2= j1-0;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;

case 7: if(cc==4)
break;
i2= i1-0;
j2= j1+1;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
flag=1;
break;
}
}
cc++;
}
}
if(flag==1)
break;

ct++;
k++;
}

if(ct<n*n){
k2= (i2*n)+j2;
return k*(n*n)+k2;
}
else{
return -1;
}
}
/************************/

/*    Name: checkneigh()
Input: k1, k2, size of array row/column, 2D-array of pointers
Output: returns 1 if true, 0 if fails.
Description: Checks the neighbouring 4 vaues and find if there are more than 1 neighbours of the same set.
*/
int checkneigh(int k1, int k2, int n, node ***arr)
{
int i= k2/n;
int j= k2%n;
int ii= k1/n;
int jj= k1%n;

int ct=0;
if(i>0 && findset(arr[i-1][j])==findset(arr[ii][jj]))
ct++;
if(i<n-1 && findset(arr[i+1][j])==findset(arr[ii][jj]))
ct++;
if(j>0 && findset(arr[i][j-1])==findset(arr[ii][jj]))
ct++;
if(j<n-1 && findset(arr[i][j+1])==findset(arr[ii][jj]))
ct++;

if(ct>1)
return 0;
else
return 1;
}
/****************************/

/*    Name: valid_next()
Input: starting k, size of array row/column, 2D-array of pointers
Output: returns the value of k2 or -1 if fails.
Description: Finds the next valid points of the flow.
*/
int valid_next(int k, int n, node ***arr)
{
int i1, i2, j1, j2, a, b, kk, stat,ct=0;
int flag=0;
i1= k/n;
j1= k%n;
kk= rand()%4;
switch(kk)
{
case 0: i2= i1-1;
j2= j1-0;
if(i2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

case 1:	i2= i1-0;
j2= j1-1;
if(j2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

case 2: i2= i1+1;
j2= j1-0;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

case 3: i2= i1-0;
j2= j1+1;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

case 4: if(ct==4)
break;
i2= i1-1;
j2= j1-0;
if(i2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

case 5:	if(ct==4)
break;
i2= i1-0;
j2= j1-1;
if(j2>=0 && i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

case 6: if(ct==4)
break;
i2= i1+1;
j2= j1-0;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

case 7: if(ct==4)
break;
i2= i1-0;
j2= j1+1;
if(i2<n && j2<n){
if(arr[i2][j2]->path_number==0){
stat= checkneigh(k, (n*i2 + j2),n,arr);
//printf("%d\n",stat);
if(stat){
flag=1;
break;
}
}
}
ct++;

}
//printf("flag- %d\n",flag);
if(flag==0)
return -1;
if(flag){
//printf("value sent- %d\n", i2*n + j2);
return (i2*n)+j2;
}
}
/********************/

Input:  2D-array of pointers, size of array row/column, path number
Output: returns 1 if a new path can be (or, is) added, 0 if not.
Description: Creates a new flow path.
*/
int addpath(node ***arr, int n, int ptno)
{

int a,b,k1,k2;
int i1,j1,i2,j2;
k2= neighbour( n, arr);

return 0;

k1= k2/(n*n);
k2= k2%(n*n);
//printf("%d %d\n",k1,k2);

i1= k1/n;
j1= k1%n;
i2= k2/n;
j2= k2%n;
//printf("%d %d\n",i1,j1);
//printf("%d %d\n",i2,j2);

//found i1,j1 and i2,j2
arr[i1][j1]->endpoint= 1;

arr[i2][j2]->path_number= ptno;
arr[i1][j1]->path_number= ptno;

node *n1, *n2;
n1= arr[i1][j1];
n2= arr[i2][j2];
n1= findset(n1);
n2= findset(n2);
setunion(n1, n2);

while(1){
i1= i2;
j1= j2;
k1= (i1*n)+j1;

/******/
k2= valid_next(k1,n,arr);
//printf("k2- %d\n",k2);

if(k2==-1){
arr[i1][j1]->endpoint= 1;
break;
}

i2=k2/n;
j2=k2%n;
//printf("%d %d\n",i2,j2);
arr[i2][j2]->path_number= ptno;
node *n1, *n2;
n1= arr[i1][j1];
n2= arr[i2][j2];
n1= findset(n1);
n2= findset(n2);
setunion(n1,n2);
}
return 1;
}
/************************/

/*    Name: printtable()
Input:  2D-array of pointers, size of array row/column
Output: --void--
Description: Prints the question table and the corresponding solution table.
*/
void printtable(node ***arr, int n)
{
int i,j;
printf("Table to be solved:\n");
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(arr[i][j]->endpoint ==1){
if(arr[i][j]->path_number/10==0)
printf("| %d |",arr[i][j]->path_number);
else
printf("| %d|",arr[i][j]->path_number);
}
else if(arr[i][j]->path_number==0)
printf("| X |");
else
printf("|   |");
}
printf("\n");
}
printf("\n\nThe solution to the above table:\n");
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(arr[i][j]->path_number != 0){
if(arr[i][j]->path_number/10==0)
printf("| %d |",arr[i][j]->path_number);
else
printf("| %d|",arr[i][j]->path_number);
}
else
printf("| X |");
}
printf("\n");
}

}
/******************/

/*    Name: main()
Input:  --void--
Output: returns 1
Description: The driver function.
*/
int main(void)
{
srand((unsigned int) time (NULL));
int i, j;
int ct = 1;

// Size of board
int n = 7;

node*** pointers= (node ***)malloc(n*sizeof(node **));
for (i=0; i<n; i++)
pointers[i] = (node **)malloc(n*sizeof(node *));

initboard(pointers, n);

while(1) {
if (i==0){
//printf("Failure\n");
break;
}
else {
ct++;
//printf("Success\n");
}
}
printtable(pointers,n);

return 0;
}
/***********************/

```

### Output:

```Table to be solved:
|   ||   ||   ||   ||   ||   || 4 |
|   ||   ||   ||   ||   || 3 ||   |
|   ||   || 2 || 2 ||   ||   || 3 |
|   ||   ||   ||   || X ||   || 1 |
|   ||   || 6 ||   ||   || 7 || 7 |
| 5 || 4 ||   || X ||   || X || 1 |
|   || 5 ||   || 6 ||   ||   ||   |

The solution to the above table:
| 4 || 4 || 4 || 4 || 4 || 4 || 4 |
| 4 || 1 || 1 || 1 || 1 || 3 || 3 |
| 4 || 1 || 2 || 2 || 1 || 1 || 3 |
| 4 || 1 || 1 || 1 || X || 1 || 1 |
| 4 || 4 || 6 || 1 || 1 || 7 || 7 |
| 5 || 4 || 6 || X || 1 || X || 1 |
| 5 || 5 || 6 || 6 || 1 || 1 || 1 |
```