Showing posts with label Algorithm. Show all posts
Showing posts with label Algorithm. Show all posts

Saturday, July 28, 2012

ANSI C: N Queens Problem


Introduction

The n queens puzzle is the problem of placing n chess queens on an n*n chessboard so that no two queens attack each other.

The Program

queens_ori.c


#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

/**
 * The n queens puzzle is the problem of
 * placing n chess queens on an n×n chessboard
 * so that no two queens attack each other. 
 */

// define some values to shorten the code

// status message and params
// printf(statmsg, statparam); will become
// printf("there are %d queens in a %d x %d chessboard\n\n answer(s): \n\n", number_of_queens, number_of_queens, number_of_queens);
#define statmsg "there are %d queens in a %d x %d chessboard\n\n answer(s): \n\n"
#define statparam number_of_queens, number_of_queens, number_of_queens
// answer message and params
#define ansmsg "put col[%d] queen to row %d\n"
#define ansparam outIdx, col[outIdx]
int number_of_queens;  // n queens in nxn chessboard
                       // note: don't too large (ex, over 25)
int *col;  // chessboard
FILE *outptr; // output file
int cnt; // result count

// function to solve this problem
void queens( int currentCol );
// function to determing whether the status is valid
bool promising( int currentCol );

int main()
{

  cnt = 0;
  
  printf("please enter the number of queens:\n");
  scanf("%d", &number_of_queens);
  // col[0] not used, start from col[1]
  col = (int*) malloc ((number_of_queens+1)*sizeof(int));
  outptr = fopen("QueenSol.txt", "w" );

  printf(statmsg, statparam);
  fprintf(outptr, statmsg, statparam);
  // call function to solve problem
  // pass 0 into it but it will then start from 1
  queens( 0 );

  if (cnt == 0) {
     printf(" no result\n\n");
     fprintf(outptr, " no result\n\n");
  }
  fclose( outptr );
  free(col);

  system("PAUSE");
  return 0;
}

void queens( int currentCol )
{
 int row;    // row index to test
 int outIdx; // index for output result
 if( promising(currentCol) )  // if valid
 {
   if( currentCol == number_of_queens )  // output if at latest col
   {
     cnt++;
     for( outIdx = 1; outIdx <= number_of_queens; outIdx++ )
     {
       printf(ansmsg, ansparam);
       fprintf(outptr, ansmsg, ansparam);
     }
     printf("\n\n");
     fprintf(outptr, "\n\n");
   }

   // call function recursively if not latest col
   else
   {
     for(row = 1; row <= number_of_queens; row++ )  // test next col from row 1 to row n
     {
       col[currentCol + 1] = row;
       queens( currentCol + 1 );
     }
   }

 }
}

// check whether current stats is valid
bool promising( int currentCol )
{
  int idx = 1; // loop index
  bool isValid = true; // is valid? default to true


  // test whether previous queens will attack current queen
  while( (idx < currentCol) && isValid )
  {
    // found invalid status
    // in the same row
    // or diagonal
    if( (col[currentCol] == col[idx])
        || (abs( col[currentCol] - col[idx]) == currentCol - idx) )
    {
        isValid = false;  // set to invalid, stop loop
    }
    idx++;  // increase index and contiune

  }
  return isValid;
}



The Result




Reference
http://en.wikipedia.org/wiki/Eight_queens_puzzle


Download
The files are at github
https://github.com/benbai123/C_Cplusplus_Practice/tree/master/C_Algorithm/N_Quenes

Sunday, July 22, 2012

ANSI C: Hamiltonian cycle


Introduction

A Hamiltonian path (or traceable path) is a path in an undirected graph that visits each vertex exactly once. A Hamiltonian cycle (or Hamiltonian circuit) is a Hamiltonian path that is a cycle.

In this post, we will implement an ANSI C program that will display all Hamiltonian cycle of a given graph array.

The Program

hamiltonian.c

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

/**
 * A Hamiltonian path (or traceable path)
 * is a path in an undirected graph that
 * visits each vertex exactly once.
 * A Hamiltonian cycle (or Hamiltonian circuit) is
 * a Hamiltonian path that is a cycle.
 * From wiki: http://en.wikipedia.org/wiki/Hamiltonian_path
 */

// the number of nodes in the test graphic
int node_amount = 12;
// the number of Hamiltonian cycles
int hamiltonian_cycle_amount = 0;

// Graph Representation with nodes
// not use [0][x] and [x][0]
int graph_array[13][13] = {
                 0,0,0,0,0,0,0,0,0,0,0,0,0,
                 0,0,1,0,0,1,0,0,0,0,0,0,0,
                 0,1,0,1,0,0,0,1,1,0,0,0,0,
                 0,0,1,0,1,0,0,0,1,0,0,0,0,
                 0,0,0,1,0,1,0,0,0,1,0,0,0,
                 0,1,0,0,0,0,1,0,0,0,1,0,0,
                 0,0,0,0,0,1,0,1,0,0,0,1,0,
                 0,0,1,0,0,0,1,0,1,0,0,0,0,
                 0,0,1,1,0,0,0,1,0,1,0,0,0,
                 0,0,0,0,1,0,0,0,1,0,1,0,1,
                 0,0,0,0,0,1,0,0,0,0,0,1,0,
                 0,0,0,0,0,0,1,0,0,0,1,0,1,
                 0,1,0,0,0,0,0,0,0,1,0,1,0
                };

// the array store the result through recursive
int result_array[13] = {0};

/**
 * The function that find all Hamiltonian cycle
 * and output to console
 * param node_index: int, nth node in path
 */
void hamiltonian ( int node_index );
/**
 * The function that check whether current node
 * is valid in Hamiltonian cycle.
 */
bool promising ( int node_index );

int main()
{
  printf("\n");
  result_array[1] = 1;  // start from first node
  hamiltonian( 1 );  // start to find all Hamiltonian cycles recursively

  if( hamiltonian_cycle_amount == 0 )  // no Hamiltonian cycles found
   printf("\nThere is no Hamiltonian cycles in this graph\n\n");

  printf("\n");

  system("PAUSE");
  return 0;
}

void hamiltonian ( int node_index )
{
  int j, k;
  if( promising(node_index) )  // current node is valid in a Hamiltonian cycles
  {
     if( node_index == (node_amount) )  // at latest node
     {  hamiltonian_cycle_amount = 1;  // increase hamiltonian_cycle_amount
        printf(" v%d", result_array[1]);  // print out the result
        for( k = 2;k <= node_amount;k ++ )
          printf(" → v%d", result_array[k]);
        printf("\n\n");
     }
     else  // not latest node
     {
        for( j = 2;j <= node_amount;j ++ )  // recursively scan from second node to latest node
        {
           result_array[node_index+1] = j; // store result
           hamiltonian( node_index+1 );  // call function recursively
        }
     }
  }

}

bool promising ( int node_index )
{
  int j, k;
  bool isValid = true; // default to valid

  j = 1;

  if (node_index == 1) // first node, valid
    isValid =  true;
  if( (node_index == (node_amount)) && (!graph_array[result_array[node_index]][result_array[1]]) )
     isValid =  false;  // latest node but not connected to first node, invalid

  else if( ( node_index > 1 ) && (!graph_array[result_array[node_index-1]][result_array[node_index]]) )
     isValid =  false;  // not connected between current node and previous node, invalid

  else
  {
    while( (j < node_index) && isValid)  // check all previous nodes
    {
       if( result_array[node_index] == result_array [j] )
         isValid = false;  // current point already in path, invalid
       j++;
    }
  }
  return isValid;  // return whether current node is valid
}

The Result


Reference
http://en.wikipedia.org/wiki/Hamiltonian_path

Download
The files at github
https://github.com/benbai123/C_Cplusplus_Practice/tree/master/C_Algorithm/Hamiltonian_Cycle

Sunday, July 15, 2012

ANSI C: Coloring Problem


Introduction

The Coloring Problem is coloring the vertices of a graph such that no two adjacent vertices share the same color, in this post, we will try to implement it in ANSI C.

The Program

Coloring_Problem.c

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>

/**
 * Graph coloring
 * Coloring the vertices of a graph such that
 * no two adjacent vertices share the same color;
 * Wiki: http://en.wikipedia.org/wiki/Graph_coloring
 */

FILE *res;

// The 2-D array denotes a graph adjacent status,
// For example, [a, b] are adjacent vertices,
// [a, d] are also adjacent vertices.
// the index starts from 1,
// [0][x] and [x][0] are not considered
                           // #,a,b,c,d,e,f
int _adjacentMatrix [7][7] = {0,0,0,0,0,0,0, // not use
               0,0,1,0,1,0,0, // a
               0,1,0,1,0,1,0, // b
               0,0,1,0,0,0,1, // c
               0,1,0,0,0,1,0, // d 
               0,0,1,0,1,0,1, // e
               0,0,0,1,0,1,0  // f
              };

int _verticeAmount = 6;  // six points

// three colors
char _colors[4][20] = { "NULL",
                      "RED",
                      "GREEN",
                      "WHITE"
                      };

// temp store the result
int _result[7] = {0};

void m_coloring( int i );
bool promising( int i );

int main()
{
  res = fopen("result.txt", "w");
  printf("there are %d vertices, the color combinations are as below: \n\n", _verticeAmount);
  fprintf(res, "there are %d vertices, the color combinations are as below: \n\n", _verticeAmount);
  m_coloring( 0 );
  fclose( res );



      system("PAUSE");
      return 0;
}

/**
 * The coloring function that will recursively create different combinations
 * then call promising function to test whether the combination is valid.
 *
 * Three actions:
 *         Output the result if
 *         the current combination is valid and reach the latest vertice.
 *         
 *         Continue add color - vertice to extend combination if
 *         the current combination is valid but not reach the latest vertice.
 *
 *         Terminate the recursive to skip any combination
 *         that starts with the current combination if
 *         the current combination is not valid.
 *
 */
void m_coloring ( int i )
{
  int color; // color index for test
  int j; // index for output result

  if( promising(i) )  // coloring success
  {
    if( i == _verticeAmount ) // is latest vertice
    {
      for( j = 1;j <= _verticeAmount;j ++ )  // output the result
      {
        if (j > 1) {
          printf(",");
          fprintf(res, ", ");
        }
        printf("%s", _colors[_result[j]]);
        fprintf(res, "%s", _colors[_result[j]]);
      }
      printf("\n\n");
      fprintf(res, "\n\n");

    }

    else  // not latest vertice
    {
       for( color = 1;color <= 3;color ++ )  // test each color
       {
          _result[i+1] = color;  // set color to next vertice
          m_coloring(i+1); // recursive to continue combination
       }
    }
  }
}

/**
 * check whether has adjacent virtice share color with current virtice
 * return bool
 * true: no adjacent vertice share the same color, can 
 * continue this combination
 * false: has adjacent vertice share the same color,
 * this combination should be terminated
 */
bool promising( int currentVerticeIndex )
{
   int j = 1; // start from first virtice
   bool sw = true;  // default to success (no two adjacent vertices share the same color)

   while( (j < currentVerticeIndex) && sw)  // scan all previous vertices
   {
      // if found an adjacent vertice share the same color
      if( _adjacentMatrix[currentVerticeIndex][j] && (_result[currentVerticeIndex] == _result[j])) {
        sw = false;  // set to fail (has two adjacent vertices share the same color)
        break;
      }
      j++;
   }

   return sw;  // return the result (success or fail)
}


The promising function will return whether current combination is valid.

The m_coloring function that will recursively create different combinations then call promising function to test whether the combination is valid. It will do three different actions with respect to the different status and the result of promising function:

1. Output the result if the current combination is valid and reach the latest vertice.

2. Continue add color - vertice to extend combination if the current combination is valid but not reach the latest vertice.

3. Terminate the recursive to skip any combination that starts with the current combination if the current combination is not valid.

The Result



Reference
Wiki
http://en.wikipedia.org/wiki/Graph_coloring


Download
Files at github
https://github.com/benbai123/C_Cplusplus_Practice/tree/master/C_Algorithm/Coloring_Problem