CS 201 - Homework 5 - IntLists

Due: Friday 10/20 at 5pm

This assignment has two programming problems. Both of them relate to the IntList class, which is an implementation of lists of integers different from the List class in Bailey's text. While Bailey's List class provides a general, object-oriented implementation, the IntList and IntListOps classes used in this assignment are inspired by functional languages, such as LISP, Scheme, and ML.

When you have completed the assignment, please submit your programs (HW5IntListOps.java and HW5IntListListOps.java) using the HW 5 submission page.


Lab exercises:

You'll again be using Eclipse to develop your code. During lab, we will help you get started on HW5:

Start by downloading hw5.zip, and extract this archive in your cs201 directory. This will create a new hw5 directory there:

    > cd cs201
    [download hw5.zip and save it here]
    > unzip hw5.zip
    > cd hw5
    > ls
    HW5IntListListOps.java      IntList.java         IntListOpsTest.java
    HW5IntListListOpsTest.java  IntListList.java     ListException.java
    HW5IntListOps.java          IntListListOps.java
    HW5IntListOpsTest.java      IntListOps.java
Next, like last time, proceed as follows: Next, in the "Package Explorer" (or "Project Explorer"), expand "hw5" and within that expand "(default package)". Double-click on any of the java files to open them. Once you have a runnable application open (any of the 3 files ending in "...OpsTest.java"), click on the green arrow button at the top to run it.


Problem 1: IntList Methods

In this problem, you will define three methods that manipulate integer lists. Skeletons for these methods appear in the file HW5IntListOps.java. This file is configured so that you can use head, tail, prepend, etc. as abbreviations for IntList.head, IntList.tail, IntList.prepend, etc. You can test your methods by running the file HW5IntListOpsTest.java.

Start by studying the code in IntList.java and IntListOps.java. You can test the operations by running the program IntListOpsTest.java.

Note: For full credit you must use recursion, just like the example methods in IntListOps.java. Loops and global (static) variables are not allowed.

Here are contracts and test case results for the three methods you'll have to write:

public static boolean isSorted(IntList L)
Returns true if the integers in L are sorted from low to high, and false otherwise.

Examples:

isSorted([]) = true
isSorted([1]) = true
isSorted([1, 2]) = true
isSorted([1, 1]) = true
isSorted([2, 1]) = false
isSorted([1, 2, 3, 4, 5]) = true
isSorted([1, 2, 3, 4, 0]) = false
isSorted([1, 5, 3, 4, 2]) = false

public static IntList remove(int i, IntList L)
Returns a new list that contains all of the elements of L in the same order except for occurrences of i, which are removed.

Examples:

remove(0, [4, 2, 3, 4, 1, 3, 4, 2, 4, 3]) = [4, 2, 3, 4, 1, 3, 4, 2, 4, 3]
remove(1, [4, 2, 3, 4, 1, 3, 4, 2, 4, 3]) = [4, 2, 3, 4, 3, 4, 2, 4, 3]
remove(2, [4, 2, 3, 4, 1, 3, 4, 2, 4, 3]) = [4, 3, 4, 1, 3, 4, 4, 3]
remove(3, [4, 2, 3, 4, 1, 3, 4, 2, 4, 3]) = [4, 2, 4, 1, 4, 2, 4]
remove(4, [4, 2, 3, 4, 1, 3, 4, 2, 4, 3]) = [2, 3, 1, 3, 2, 3]

public static IntList removeDuplicates(IntList L)
Returns a new list that contains only one occurrence of each integer that occurs in L. The order of the integers in the resulting list does not matter.

Examples:

removeDuplicates([]) = []
removeDuplicates([3, 5, 2, 1, 4]) = [3, 5, 2, 1, 4]
removeDuplicates([4, 2, 3, 4, 1, 3, 4, 2, 4, 3]) = [4, 2, 3, 1]

Don't forget to comment your methods!


Problem 2: IntListList Methods

In this problem, you will define three (or four) methods that manipulate lists whose elements are integer lists. These are instances of the class IntListList, which supports the same methods as IntList except for a change in type. For instance, the head of an IntListList is an IntList, and the tail of an IntListList is an IntListList. Start by studying the code in IntListList.java and IntListListOps.java.

Skeletons for the methods you'll have to write appear in the file HW5IntListListOps.java. This file is configured so that you can use head, tail, prepend, etc as abbreviations for IntListList.head, IntListList.tail, IntListList.prepend, etc. However, some problems require class methods from other classes; for these, you will have to use an explicit prefix, for example, IntList.head, IntListOps.length, HW5IntListOps.isSorted, etc. You can test your methods by running the program HW5IntListListOpsTest.java.

As in problem 1, you must use recursion for full credit, and you may not use loops or global variables.

Here are contracts and test case results for the four methods:

public static IntListList filterSorted(IntListList L)
Returns a list of all elements of L that are sorted lists.

Examples:

filterSorted([]) = []
filterSorted([[]]) = [[]]
filterSorted([[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2], 
             [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]) 
  = [[], [1], [1, 2], [1, 2, 3]]
filterSorted([[2, 1], [2, 3, 1], [3, 1, 4, 2], [], [1, 2, 3, 4], 
             [2, 1, 3], [1, 2, 3], [2, 1], [1]]) 
  = [[], [1, 2, 3, 4], [1, 2, 3], [1]]
    

public static IntListList mapPrepend(int i, IntListList L)
Returns a list the same length as L in which each element is the corresponding element of L with the integer i prepended in front.

Examples:

mapPrepend(5, []) = []
mapPrepend(6, [[]]) = [[6]]
mapPrepend(7, [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2], 
               [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]) 
  = [[7], [7, 1], [7, 1, 2], [7, 2, 1], [7, 1, 2, 3], [7, 1, 3, 2], 
     [7, 2, 1, 3], [7, 2, 3, 1], [7, 3, 1, 2], [7, 3, 2, 1]]
mapPrepend(8, [[2, 1], [2, 3, 1], [3, 1, 4, 2], [], [1, 2, 3, 4], 
               [2, 1, 3], [1, 2, 3], [2, 1], [1]]) 
  = [[8, 2, 1], [8, 2, 3, 1], [8, 3, 1, 4, 2], [8], [8, 1, 2, 3, 4], 
     [8, 2, 1, 3], [8, 1, 2, 3], [8, 2, 1], [8, 1]]
     

public static IntListList subsequences(IntList L)
Returns a list of all subsequences of L. A subsequence of L is a list that is obtained from L by deleting zero or more elements and maintaining the relative order of the undeleted elements. The order of components lists in the result returned by subsequences does not matter. (Hint: This one is tricky - think hard! You might want to employ the mapPrepend() method above.)

Examples:

subsequences([]) = [[]]
subsequences([1]) = [[], [1]]
subsequences([1, 2, 3]) 
  = [[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
subsequences([3, 1, 4, 2]) 
  = [[], [2], [4], [4, 2], [1], [1, 2], [1, 4], [1, 4, 2], 
     [3], [3, 2], [3, 4], [3, 4, 2], [3, 1], [3, 1, 2], [3, 1, 4], [3, 1, 4, 2]]
     

This last method is optional, for extra credit

public static IntListList longest(IntListList L)
Returns a list containing all the components that have the longest length in L. (This one is also tricky - what do you expect from an extra credit problem? Try to come up with a recursive approach. Hint: there are three cases when comparing the lengths of two lists.)

Examples:

longest([]) = []
longest([[]]) = [[]]
longest([[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2], 
         [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]) 
  = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
longest([[2, 1], [2, 3, 1], [3, 1, 4, 2], [], [1, 2, 3, 4], 
        [2, 1, 3], [1, 2, 3], [2, 1], [1]]) 
  = [[3, 1, 4, 2], [1, 2, 3, 4]]