/**********************************************************************
 * walk.c --- Recursively enumerate the ways in which a robot may
 *            walk.
 *
 * This program enumerates all the ways a robot may walk n meters,
 * where n is input by the user.  The robot may take steps of one or
 * two meters.
 *
 * The program queries the user for n and terminates when zero is
 * entered or if an overly large (> MAXWALK) value is entered.
 **********************************************************************/


#include <stdio.h>


#define MAXWALK 20               /* Maximum walk length. */
#define STRLEN 2 * MAXWALK + 3   /* Maximum length of the walk string */


/* Function prototypes. */

void walk(char *sofar, int remain);
void strcp(char *dest, char *src);
void strct(char *dest, char *src);


/**********************************************************************
 * main
 **********************************************************************/

int main(void)
{
   int length;   /* length of walk */

   printf("\nEnter 0 to exit.\n");
   printf("Maximum walk length is %d.\n", MAXWALK);

   /* query for walk length and then enumerate the walks */

   while (1)
   {
      printf("\nLength of walk: ");
      scanf("%d", &length);

      if (length == 0 || length > MAXWALK)
         break;

      printf("Walks of length %d:\n", length);

      /* Begin recursively enumerating the possible walks. */

      walk("", length);
   }

   return 0;
}


/**********************************************************************
 * walk --- Recursively enumerate robot walks.
 *
 * Parameters:
 *
 *    sofar --- A string containing the robot's steps so far.
 *
 *    remain --- The remaining walk distance.
 **********************************************************************/

void walk(char *sofar, int remain)
{
   char path[STRLEN];   /* Temp string, used to construct the new
                         * walk.
                         */

   switch (remain)
   {
      /* We're done, print the walk. */
 
      case 0:
         printf("%s\n", sofar);
         break;

      /* We're also done, as there is only one way to walk the remaining
       * distance.
       */

      case 1:
         printf("%s 1\n", sofar);
         break;

      /* Robot has two alternatives: step of length two, step of
       * length one.  Recursively enumerate each alternative.
       */

      default:
         strcp(path, sofar);
         strct(path, " 2");
         walk(path, remain - 2);
         strcp(path, sofar);
         strct(path, " 1");
         walk(path, remain - 1);
         break;
   }
}


/**********************************************************************
 * strcp --- My own version of strcpy().
 *
 * Parameters:
 *
 *    dest --- The buffer to which the source string will be copied.
 *
 *    src --- The string to be copied.
 **********************************************************************/

void strcp(char *dest, char *src)
{
   /* Copy source characters into the buffer until we hit the
    * terminating NULL character.
    */

   while (*src != '\0')
   {
      *dest = *src;
      dest++;
      src++;
   }

   *dest = '\0';     /* Terminate the new string in dest. */
}


/**********************************************************************
 * strct --- My own version of strcat().
 *
 * Parameters:
 *
 *    dest --- The string to which src is concatenated.
 *
 *    src --- The string concatenated onto dest.
 **********************************************************************/

void strct(char *dest, char *src)
{
   /* Find the end of the destination string. */

   while (*dest != '\0')
      dest++;

   /* Copy the source string onto the end of the destination string. */

   strcp(dest, src);
}
