31C. Example: Is One List a Prefix of Another?

Say that list A is a prefix of list B if you can convert A into B by adding zero or more numbers to the end of A. For example, [1, 3] is a prefix of [1, 3, 5]). By our definition, every list is a prefix of itself, and the empty list is a prefix of every list.

Let's write equations that define function isPrefix(A, B), which is true if list A is a prefix of list B. And indicates logical and (&& in C++).

(isPrefix.1)    isPrefix([ ], B) = true
(isPrefix.2)    isPrefix(A, [ ]) = false   (when A ≠ [ ])
(isPrefix.3)    isPrefix(A, B) = head(A) == head(B)  andisPrefix(tail(A), tail(B))   (when A ≠ [ ] and B ≠ [ ])

The first two equations should be evident; the empty list is a prefix of every list, and a nonempty list is not a prefix of an empty list. Equation (isPrefix.3) should be more obvious through an example.

   isPrefix([3, 5], [3, 5, 7, 9])
   = 3 == 3 andisPrefix([5], [5, 7, 9])  by (isPrefix.3)
   = true andisPrefix([5], [5, 7, 9])  since 3 == 3 is true
   = isPrefix([5], [5, 7, 9])  since true andCC
   = 5 == 5 andisPrefix([ ], [7, 9])  by (isPrefix.3)
   = true andisPrefix([ ], [7, 9])
   = isPrefix([ ], [7, 9])
   = true  by (isPrefix.1)

Here is a C++ definition of isPrefix based on equations (isPrefix.1), (isPrefix.2) and (isPrefix.3).

  bool isPrefix(ConstList A, ConstList B)
  {
    if(A == NULL)
    {
      return true;
    }
    else if(B == NULL)
    {
      return false;
    }
    else
    {
      return A->head == B->head && isPrefix(A->tail, B->tail)
    }
  }

Exercises

  1. The following equation about isPrefix is false. Give a counterexample that shows it is wrong. Evaluate the two sides for your counterexample and show that they are not equal.

      isPrefix(h : t, L) = isPrefix(t, L)

    Answer

  2. Using equations (isPrefix.1–isPrefix.3), show an evaluation of isPrefix([2, 3, 4], [2, 4, 3]) by only replacing expressions by equal expressions. Answer

  3. Using equations (isPrefix.1–isPrefix.3), show an evaluation of isPrefix([2, 3], [2]) by only replacing expressions by equal expressions. Answer

  4. Write equations for function smallest(L), which yields the smallest member of nonempty list L. For example, smallest([2, 3, 4]) = 2 and smallest([6, 4, 8, 7]) = 4. Your equations should not try to define smallest([ ]), since the list is required to be nonempty. You can use function min(x, y) to compute the smaller of two integers x and y. Answer

  5. Write a definition of smallest based on your equations. Answer

  6. Write equations for function prefix(L, n), which yields the length n prefix of list L. For example, prefix([2, 4, 6, 8, 10], 3) = [2, 4, 6]. If n is larger than the length of L then prefix(L, n) should return L. For example, prefix([2, 4, 6, 8, 10], 50) = [2, 4, 6, 8, 10]. Answer

  7. Convert your equations for prefix to a C++ definition of prefix(L, n). Answer