CS13002 PDS Lab, Spring 2003, Section 1/A

Solution of Assignment 8

The program

#include <stdio.h>

char *permArray = NULL;
int **nkArray = NULL;

int factorial ( int n )
/* Returns n! (factorial of n) */
{
   int retval = 1, i;

   for (i=1;i<=n;i++) retval *= i;
   return(retval);
}

void genPerm ( char **A , int n )
/* Generate the list of all permutations of 1,...,n from the list of
   all permutations of 1,...,n-1 */
{
   char *B = NULL;
   int i,j,k,l,L,m;

   if (n == 1) {  /* Basis case : no previous list is available */
      (*A) = (char *)malloc(sizeof(char));
      (*A)[0] = 1;
      return;
   }

   /* Now n > 1 and the list for n-1 is passed via A. This list is
      to be modified to the list for n. The resulting list is again
      saved in A. So it is necessary to reallocate memory to A. */

   /* Length of the previous list */
   l = (n-1)*factorial(n-1);

   /* make a local copy of the previous list in B */
   B = (char *)malloc(l*sizeof(char));
   for (i=0;i<l;i++) B[i] = (*A)[i];

   /* Now A can be rellaocated memory. One can use realloc() for that.
      Here I free the memory assigned to A (actually *A) and then allocate
      fresh memory to it. */
   free(*A);
   (*A) = NULL;
   L = n * factorial(n);  /* Size of the new list */
   (*A) = (char *)malloc(L*sizeof(char));

   /* Initialize : j is the index for reading from B and k is the index
      for writing to A */
   j = k = 0;
   while (j<l) {
      /* For each permutation of 1,...,n-1 one can insert n in n different
         locations to get n different permutations of 1,...,n. */
      for(i=0;i<n;i++) {
         for (m=0;m<i;m++) (*A)[k++] = B[j+m];  /* Copy the first part */
         (*A)[k++] = n;                         /* Insert n */
         for (m=i;m<n-1;m++) (*A)[k++]=B[j+m];  /* Copy the remaining part */
      }
      j += n-1;  /* Consider the next permutation of 1,...,n-1 */
   }
   free(B);      /* Free local memory */
}

int countDescentEnum ( char *A , int n )
/* Enumerative counting of the Eulerian numbers <n,k> for k=0,...,n-1 */
{
   int i,j,k,l;
   int *ndesc;   /* The numbers <n,k> are grown here */

   ndesc = (int *)calloc(n,sizeof(int));  /* Allocate and intialize to zero */

   l = n * factorial(n);  /* Size of the list of permutations */
   j = 0;  /* j is the index for reading from A */
   while (j<l) {
      k=0;  /* k counts the number of descents in this permutation */
      for (i=0;i<n-1;i++)
         if (A[j+i]>A[j+i+1])  /* A descent is detected */
            k++;               /* Increment k */
      ndesc[k]++; /* k decsents have been found, record this info */
      j+=n;  /* Next permutation */
   }

   /* Print the Eulerian numbers <n,k> obtained by exhaustive enumeration */
   printf("n = %d  Enumerative ",n);
   for (k=0;k<n;k++) printf(" %5d ",ndesc[k]);
   printf("\n");
}

int rec ( int n , int k )
/* Implements the recursive definition of <n,k> */
{
   if (k==0) return(1);
   if (n<=k) return(0);
   return((k+1)*rec(n-1,k)+(n-k)*rec(n-1,k-1));
}

int countDescentRec ( int n )
/* Recursive counting of the Eulerian numbers <n,k> for k=0,...,n-1 */
{
   int k;

   printf("       Recursive   ");
   for (k=0;k<n;k++) printf(" %5d ",rec(n,k));
   printf("\n");
}

int countDescentIter ( int **A , int n )
/* Iterative counting of the Eulerian numbers <n,k> for k=0,...,n-1 */
{
   int k;

   if (n==1) A[1][0] = 1; /* Basis case */
   else {
      A[n][0] = 1;        /* Basis case */

      /* Use the values stored in A[n-1] to obtained A[n][k]. */
      for (k=1;k<n-1;k++) A[n][k] = (k+1)*A[n-1][k]+(n-k)*A[n-1][k-1];

      A[n][n-1] = 1;      /* Using the recursive definition requires
                             reading A[n-1][n-1]. This array location
                             does not exist and this quantity has not
                             been computed. On the other hand, we know
                             that n,n-1,...,2,1 is the only permutation
                             of 1,...,n with n-1 descents. */
   }
   printf("       Iterative   ");
   for (k=0;k<n;k++) printf(" %5d ",A[n][k]);
   printf("\n");
}

int main ()
{
   int i,k,n,N=8;

   printf("                   ");
   for (k=0;k<N;k++) printf(" k = %d ",k);
   printf("\n");

   /* Allocate memory to the array needed for the iterative method */
   nkArray = (int **)malloc((N+1)*sizeof(int *));
   nkArray[0] = NULL;
   for (i=1;i<=N;i++) nkArray[i] = (int *)malloc(i*sizeof(int));

   for (n=1;n<=N;n++) {
      genPerm(&permArray,n);          /* Generate the list of permutations
                                         from the older list */
      countDescentEnum(permArray,n);  /* Enumerative counting */
      countDescentRec(n);             /* Recursive counting */
      countDescentIter(nkArray,n);    /* Iterative counting */
   }

   /* Free memory allocated to the array needed for the iterative memory */
   for (i=1;i<=N;i++) free(nkArray[i]);
   free(nkArray);

   /* Free memory allocated to the permutation array */
   free(permArray);
}

The output

                    k = 0  k = 1  k = 2  k = 3  k = 4  k = 5  k = 6  k = 7 
n = 1  Enumerative      1 
       Recursive        1 
       Iterative        1 
n = 2  Enumerative      1      1 
       Recursive        1      1 
       Iterative        1      1 
n = 3  Enumerative      1      4      1 
       Recursive        1      4      1 
       Iterative        1      4      1 
n = 4  Enumerative      1     11     11      1 
       Recursive        1     11     11      1 
       Iterative        1     11     11      1 
n = 5  Enumerative      1     26     66     26      1 
       Recursive        1     26     66     26      1 
       Iterative        1     26     66     26      1 
n = 6  Enumerative      1     57    302    302     57      1 
       Recursive        1     57    302    302     57      1 
       Iterative        1     57    302    302     57      1 
n = 7  Enumerative      1    120   1191   2416   1191    120      1 
       Recursive        1    120   1191   2416   1191    120      1 
       Iterative        1    120   1191   2416   1191    120      1 
n = 8  Enumerative      1    247   4293  15619  15619   4293    247      1 
       Recursive        1    247   4293  15619  15619   4293    247      1 
       Iterative        1    247   4293  15619  15619   4293    247      1 


[Course home] [Home]