// L-23 MCS 360 Fri 15 Oct 2010 : percolation.cpp

/* we generate a random matrix with a loaded coin */

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;

int coin ( double p );
// p is the probability in [0,1] that 1 appears,
// if p == 0, then coin always returns 0,
// if p == 1, then coin always returns 1.

vector< vector<int> > grid ( int n, int m, double p );
// returns an n-by-m grid via nxm calls to coin(p)

void write ( int n, int m, vector< vector<int> > &A );
// writes the n-by-m matrix A

bool percolates ( int n, int m, vector< vector<int> > &A );
// returns true if there is a path in A through open
// spots from the top row to an open spot to the bottom,
// if there is a path, then the path is marked in A

bool percolates
      ( int n, int m, int i, int j,
        vector< vector<int> > &A );
// returns true if there is a path from A[i][j]
// at the top row to an open spot to the bottom,
// if there is a path, then it is marked in A 

void write_path ( int n, int m, vector< vector<int> > &A );
// writes the n-by-m matrix A with + for 1, blanks for 0,
// and 8 for the marked path

int main()
{
   cout << "give probability : ";
   double p; cin >> p;

   srand(time(0));

   cout << "give number of rows : ";
   int r; cin >> r;

   cout << "give number of columns : ";
   int c; cin >> c;

   vector< vector<int> > g = grid(r,c,p);
   cout << "the grid :" << endl;
   write(r,c,g);

   bool found = percolates(r,c,g);
   if(found)
   {
      cout << "found path : " << endl;
      write_path(r,c,g);
   }
   else
      cout << "no path found" << endl;

   return 0;
}

int coin ( double p )
{
   double r = double(rand())/RAND_MAX;

   return (r <= p) ? 1 : 0;
}

vector< vector<int> > grid ( int n, int m, double p )
{
   vector< vector<int> > A;

   A.reserve(n);
   for(int i=0; i<n; i++)
   {
      A[i].reserve(m);
      for(int j=0; j<m; j++) 
      {
         A[i][j] = coin(p);
      }
   }

   return A;
}

void write ( int n, int m, vector< vector<int> > &A )
{
   for(int i=0; i<n; i++)
   {
      for(int j=0; j<m; j++) 
         cout << " " << A[i][j];
      cout << endl;
   }
}

bool percolates
       ( int n, int m,
         vector< vector<int> > &A )
{
   for(int k=0; k<m; k++)
      if(A[0][k] == 0)
      {
         A[0][k] = 8;
         if(percolates(n,m,0,k,A)) return true;
         A[0][k] = 0;
      }
   return false;
}

bool percolates
       ( int n, int m, int i, int j, 
         vector< vector<int> > &A )
{
   if(i == n-1) return true;

   if(A[i+1][j] == 0)
   {
      A[i+1][j] = 8;
      if(percolates(n,m,i+1,j,A)) return true;
      A[i+1][j] = 0;
   }
   if(j>0)
      if(A[i+1][j-1] == 0)
      {
         A[i+1][j-1] = 8;
         if(percolates(n,m,i+1,j-1,A)) return true;
         A[i+1][j-1] = 0;
      }
   if(j<m-1)
      if(A[i+1][j+1] == 0)
      {
         A[i+1][j+1] = 8; //A[i][j] + 1;
         if(percolates(n,m,i+1,j+1,A)) return true;
         A[i+1][j+1] = 0;
      }
   return false;
}

void write_path ( int n, int m, vector< vector<int> > &A )
{
   for(int i=0; i<n; i++)
   {
      for(int j=0; j<m; j++)
         if(A[i][j] == 0)
            cout << "  ";
         else if(A[i][j] == 1)
            cout << " +";
         else
            cout << " 8";
      cout << endl;
   }
}

