		Mathematics 1201: Programming in C
		Solutions to Homework Assignment #9
			Prof. Wickerhauser

Exercise 10 of Chapter 10, pp. 292--293:
  Program:
    #include <assert.h>
    #include <stdlib.h>
    int IsLeap ( int Year );	/* Prototype of Ch 4, Ex. 9 function */
    int DaysIn( int Month, int Year ); /* Prototype of Ex. 10 function #1 */
    int IsActualDate( int Month, int Day, int Year ); /* Ex. 10 function #2 */
    int ElapsedDays( int Month, int Day, int Year ); /* Ex. 11 function */

    struct Date {  int Month; int Day; int Year; };
    typedef struct Date *Date;

    /* Return a pointer to struct Date initialized as requested: */
    Date InitDate(int Month, int Day, int Year) {
      Date New;
      New = (Date)malloc(sizeof(struct Date));  assert(New);
      New->Month = Month;  New->Day = Day;  New->Year = Year;
      return New;
    }
    /* Return 1,0,-1 if D1 is before, same as, or after D2: */
    int CompareDates( Date D1, Date D2 ) {
      if(D1->Year < D2->Year) return 1; /* D1 is earlier */
      if(D1->Year > D2->Year ) return -1; /* D2 is earlier */
      /* ...Now we know that D1->Year == D2->Year... */
      if(D1->Month < D2->Month) return 1; /* D1 is earlier */
      if(D1->Month > D2->Month ) return -1; /* D2 is earlier */
      /* ...Now we know that D1->Month == D2->Month as well... */
      if(D1->Day < D2->Day) return 1; /* D1 is earlier */
      if(D1->Day > D2->Day ) return -1; /* D2 is earlier */
      /* ...Now we know that D1->Day == D2->Day as well... */
      return 0;			/* D2 is the same date as D1 */
    }
    /* Return the number of days between D1 and D2 */
    int SubtractDates ( Date D1, Date D2 ) {
      int e1, e2;
      e1 = ElapsedDays(D1->Month, D1->Day, D1->Year);
      e2 = ElapsedDays(D2->Month, D2->Day, D2->Year);
      return (e2-e1);
    }
    /* Add the requested number of days to D */
    void AddDays ( Date D, int Days )
    {
      while( Days > 0 ) {
	Days-- ; D->Day++ ;
	if( D->Day > DaysIn(D->Month, D->Year) ) { /* carry to next Month */
	  D->Day = 1;
	  D->Month++ ;
	  if( D->Month == 13 ) {	/* carry to next Year */
	    D->Month = 1; D->Year++ ;
	  }}}
      while( Days < 0 ) {
	Days++ ; D->Day-- ;
	if( D->Day < 1 ) {		/* carry to previous Month */
	  D->Month-- ;
	  if( D->Month < 1 ) {	/* carry to previous Year */
	    D->Month = 12; D->Year-- ;
	  }
	  D->Day = DaysIn( D->Month, D->Year ); /* last day of month */
	}}
      return;
    }

    #define COMPLAIN  {printf("Unacceptable date.\n"); return 1;}
    main( void )
    {
      int d1, m1, y1, d2, m2, y2, days;      Date date1, date2;

      /* Prompt for two dates: */
      printf("Enter the first date like `mm dd yyyy': ");
      scanf( "%d %d %d", &m1, &d1, &y1 );
      if ( !IsActualDate(m1,d1,y1) ) COMPLAIN;
      date1 = InitDate(m1,d1,y1);

      printf("Enter the second date like `mm dd yyyy': ");
      scanf( "%d %d %d", &m2, &d2, &y2 );
      if ( !IsActualDate(m2,d2,y2) ) COMPLAIN;
      date2 = InitDate(m2,d2,y2);

      switch(CompareDates( date1, date2 ) ) {
      case  1:    printf("First date precedes second date.\n"); break;
      case  0:    printf("First date follows second date.\n"); break;
      case -1:    printf("First date equals second date.\n"); break;
      default:    printf("Bad return value for CompareDates().\n"); break;
      }
      printf("There are %d days from first to second date.\n",
	     SubtractDates(date1,date2) );
      printf("Enter a nonnegative number of days: "); scanf( "%d", &days );
      AddDays(date1, days); printf("First date plus %d days is %d/%d/%d.\n",
				days, date1->Month, date1->Day, date1->Year );
      AddDays(date2, -days); printf("Second date minus %d days is %d/%d/%d.\n",
				days, date2->Month, date2->Day, date2->Year );
      return 0;
    }
  Output:
    % cc ch10ex10.c ch4ex9.c ch4ex10.c ch4ex11.c
    % a.out
    Enter the first date like `mm dd yyyy': 3 4 1997
    Enter the second date like `mm dd yyyy': 3 5 1997
    First date precedes second date.
    There are 1 days from first to second date.
    Enter a nonnegative number of days: 7
    First date plus 7 days is 3/11/1997.
    Second date minus 7 days is 2/26/1997.
    %


Exercise 15 of Chapter 10, pp. 292--293.
  Program:
    #include <assert.h>
    #include <stdlib.h>

    struct Client { int ID; struct Client *Ahead; struct Client *Behind; };
    typedef struct Client *Client;
    struct Deque { Client Head; Client Tail; };
    typedef struct Deque *Deque;

    Client InitClient(int ID)    	/* Allocate a new struct Client */
    {
      Client New;
      New = (Client)malloc(sizeof(struct Client));  assert(New);
      New->Ahead = New->Behind = 0;
      New->ID = ID;
      return New;
    }

    Deque InitDeque(void)		/* Allocate a new struct Deque */
    {
      Deque New;
      New = (Deque)malloc(sizeof(struct Deque));  assert(New);
      New->Head = New->Tail = 0;
      return New;
    }

    Deque InsertHead( Deque D, Client C ) /* Insert C at the head of D. */
    {
      assert(C); assert(D);
      C->Behind = D->Head;		/* Old head is now behind C */
      if(D->Head) D->Head->Ahead = C; 	/* C is ahead of any old head */
      D->Head = C;			/* ...and is now the new head */
      C->Ahead = 0;			/* ...and has no predecessor */
      if(!D->Tail) D->Tail = C;		/* ...and is also the new tail */
      return D;
    }

    Deque InsertTail( Deque D, Client C )    /* Insert C at the tail of D. */
    {
      assert(C); assert(D);
      C->Ahead = D->Tail;		/* Old tail is now ahead of C */
      if(D->Tail) D->Tail->Behind = C; /* C is behind any old tail */
      D->Tail = C;			/* ...and is now the new tail */
      C->Behind = 0;			/* ...and has no follower */
      if(!D->Head) D->Head = C;		/* ...and is also the new head */
      return D;
    }

    Deque DeleteTail( Deque D )		/* Delete the tail Client of D.  */
    {
      Client N2L;
      assert(D);
      if(D->Tail) {
	N2L = D->Tail->Ahead;		/* next-to-last Client */
	free(D->Tail);			/* Delete old tail */
	D->Tail = N2L;			/* next-to-last is the new tail */
	if(N2L) N2L->Behind = 0;	/* ...and has no follower */
	else D->Head = 0;		/* ...or was the head, as well */
      }
      return D;
    }

    Deque DeleteHead( Deque D )		/* Delete the head Client of D.  */
    {
      Client FRU;
      assert(D);
      if(D->Head) {
	FRU = D->Head->Behind;		/* First Runner-Up Client */
	free(D->Head);			/* Delete old head */
	D->Head = FRU;			/* First Runner-Up is the new head */
	if(FRU) FRU->Ahead = 0;		/* ...and has no one in front */
	else D->Tail = 0;		/* ...or was the tail, as well */
      }
      return D;
    }

    #define SHOW_HEAD printf("Current head ID: %d; ",deq->Head?deq->Head->ID:0)
    #define SHOW_TAIL printf("Current tail ID: %d\n",deq->Tail?deq->Tail->ID:0)
    int
    main(void)
    {
      Deque deq;      Client c1, c2, c3, c4, c5, c6;
      deq = InitDeque();
      c1 = InitClient(1);      c2 = InitClient(2);      c3 = InitClient(3);
      c4 = InitClient(4);      c5 = InitClient(5);      c6 = InitClient(6);

      deq = InsertHead(deq,c1); SHOW_HEAD; SHOW_TAIL;
      deq = InsertHead(deq,c2); SHOW_HEAD; SHOW_TAIL;
      deq = InsertHead(deq,c3); SHOW_HEAD; SHOW_TAIL;
      deq = InsertHead(deq,c4); SHOW_HEAD; SHOW_TAIL;
      deq = InsertTail(deq,c5); SHOW_HEAD; SHOW_TAIL;
      deq = InsertTail(deq,c6); SHOW_HEAD; SHOW_TAIL;

      deq = DeleteHead(deq); SHOW_HEAD; SHOW_TAIL;
      deq = DeleteHead(deq); SHOW_HEAD; SHOW_TAIL;
      deq = DeleteTail(deq); SHOW_HEAD; SHOW_TAIL;
      deq = DeleteTail(deq); SHOW_HEAD; SHOW_TAIL;
      deq = DeleteTail(deq); SHOW_HEAD; SHOW_TAIL;
      deq = DeleteTail(deq); SHOW_HEAD; SHOW_TAIL;
      return 0;
    }

  Output:
    % cc ch10ex15.c
    % a.out        
    Current head ID: 1; Current tail ID: 1
    Current head ID: 2; Current tail ID: 1
    Current head ID: 3; Current tail ID: 1
    Current head ID: 4; Current tail ID: 1
    Current head ID: 4; Current tail ID: 5
    Current head ID: 4; Current tail ID: 6
    Current head ID: 3; Current tail ID: 6
    Current head ID: 2; Current tail ID: 6
    Current head ID: 2; Current tail ID: 5
    Current head ID: 2; Current tail ID: 1
    Current head ID: 2; Current tail ID: 2
    Current head ID: 0; Current tail ID: 0
    %

Extra Problem 1.  What will the following program print?
  Program:
    #include <stdio.h>
    #include <ctype.h>
    typedef struct {	char *Title;
			char *Author;
			int Pages;
			int YearPublished;    } Book;
    int main(void) {
      Book text = {"Efficient C Programming", "Mark Allen Weiss", 529, 1995};
      char *ptr;
      ptr = text.Author;
      do {
	if( isupper(*ptr) ) printf("%c. ", *ptr);
      } while(*ptr++);
      printf("\n");
      return 0;
    }
  Output:
    % cc 9-1.c
    % a.out
    M. A. W. 


Extra Problem 2.  What will the following program print?
  Program:
    #include <stdio.h>
    typedef struct Child {	char *Name;
				struct Child *Mother;
				struct Child *Father;    } Child;
    void show_parents(Child *A) {
      if(A)
	printf("%s's mom is %s, dad is %s\n",
	       A->Name,
	       A->Mother ? A->Mother->Name : "unknown",
	       A->Father ? A->Father->Name : "unknown");
      return;
    }
    int main(void) {
      Child X={"Hillary"}, Y={"Bill"}, Z={"Chelsea"};
      Z.Mother = &X;      Z.Father = &Y;
      show_parents(&X);
      show_parents(&Y);
      show_parents(&Z);
      return 0;
    }
  Output:
    % cc 9-2.c
    % a.out   
    Hillary's mom is unknown, dad is unknown
    Bill's mom is unknown, dad is unknown
    Chelsea's mom is Hillary, dad is Bill
    %
