Answers to Exam 1 Fri 23 Feb 2001

1. Analyze the following program:

       #include 
       #include 
       int main(int argc, char *argv[])
       {
          int k, cnt = 0;
          if (argc >= 2)
             for (k = 2; k < argc; k++)
                if (strcmp(argv[1],argv[k]) > 0) cnt++;
          printf("%d\n",cnt);
          return 0;
       }

   The compiler gives the executable version of this program the name a.out.
   Suppose we type in the following on the command line :

       a.out if me do be it to

   For this input line, answer the following questions :

   (a) What is the value of argc in the program?  7

   (b) What number will be printed by this program?  2
       Show your calculations for partial credit if your
       answer would be wrong.

          if < me
             > do +1
             > be +1
             < it
             < to

   (c) Explain in words what this program does :

          counts the number of words lexicographically less
          than argv[1]
                                                        +--------+
                                                        |    /20 |
                                                        +--------+

2. The function char *RemoveChar(const char s[], char c);
   returns the string s[] with all occurrences 
   of the character c removed.

   For example, RemoveChar("middle",'d') returns "mile".

   Write an iterative definition for this function :

      char *RemoveChar(const char s[], char c)
      {
         char *result = (char*)calloc(strlen(s),sizeof(char));
         int i,j = 0;
         for (i = 0; s[i] != '\0'; i++)
            if (s[i] != c) result[j++] = s[i];
         result[j] = '\0';
         return result;
      }
                                                        +--------+
                                                        |    /15 |
                                                        +--------+

3. Analyze the code for the following function

       int F(const char *s, char c, int k)
       {
          if (*s == '\0')
             return k;
          else if (*s < c)
             return F(s+1,c,k+1);
          else
             return F(s+1,c,k);
       }

   What is returned by F("group",'p',0) ?  2

   Execute the code above and complete the table below:

      -------------------------------------------
      |  call  |   Parameters of  F    | value  |
      |        |-----------------------|  on    |
      | number |    *s     |  c  |  k  | return |
      ===========================================
      |    1   |  "group"  | 'p' |  0  |   2    |
      |    2   |   "roup"  | 'p' |  1  |   2    |
      |    3   |    "oup"  | 'p' |  1  |   2    |
      |    4   |     "up"  | 'p' |  2  |   2    |
      |    5   |      "p"  | 'p' |  2  |   2    |
      |    6   |       ""  | 'p' |  2  |   2    |
      -------------------------------------------
                                                        +--------+
                                                        |    /15 |
                                                        +--------+

4. The Lucas numbers L_n are defined by

         L_1 = 1, L_2 = 3,
         L_n = L_{n-1} + L_{n-2}, for n > 2.

   The function int Lucas(int n); returns the n-th Lucas number.

   (a) Give a RECURSIVE implementation of the Lucas function:

       int Lucas(int n)
       {
          if (n == 1)
             return 1;
          else if (n == 2)
             return 3;
          else
             return Lucas(n-1) + Lucas(n-2);
       }
                                                        +--------+
                                                        |    /10 |
                                                        +--------+


   (b) Give an ITERATIVE implementation of the Lucas function: 

       int Lucas(int n)
       {
          int i, previous, current, sum;
          if (n == 1)
             return 1;
          else
          {
             previous = 1;
             current = 3;
             for (i = 3; i <= n; i++)
             {
                sum = previous + current;
                previous = current;
                current = sum;
             }
             return current;
          }
       }
                                                        +--------+
                                                        |    /15 |
                                                        +--------+


   (c) Which version (iterative or recursive) will be most efficient
       to execute? Motivate your answer.

          The recursive version will be very inefficient because of
          multiple calls to compute the same number many times.
          Therefore we prefer the iterative version.
                                                        +--------+
                                                        |    /5  |
                                                        +--------+


5. The function char *CurlyChar(char c); returns the string
   with curly braces put around the character c.
   For example, CurlyChar('k') returns "{k}".

   The analogue for strings is done by char *CurlyStr(const char *s).
   For example, CurlyStr("exam") returns "{exam}".

   Use CurlyChar and CurlyStr to define

          char *Curly(int start, int end, const char s[]);

   which puts curly braces around the characters s[k]
   for start <= k <= \tt end in a nested way.  For example, 
   Curly(0,3,"abcd") returns the string "{{{a}{b}}{{c}{d}}}".

   Write a recursive definition for Curly, using CurlyChar and CurlyStr.

   You may assume that all strings can have no more than MAX
   characters, where MAX is some globally defined constant.
   Furthermore, assume that 2.5 gets truncated to 2 if an 
   integer division of 5 by 2 is performed.

       char *Curly(int start, int end, const char s[])
       {
          int middle;
          char *left,*right;

          if (start == end)
             return CurlyChar(s[start]);
          else
          {
             middle = (start+end)/2;
             left = CurlyStr(Curly(start,middle,s));
             right = CurlyStr(Curly(middle+1,end,s));
             strcat(left,right);
             return left;
          }
       }
                                                        +--------+
                                                        |    /20 |
                                                        +--------+