CS111, Wellesley College, Spring 2003

Problem Set 8

Due on Tuesday, April 8

Take-Home Exam Announcement

By 11pm on Tuesday, April 8, Exam 2 will be posted. It is a take-home exam that will be due at 11pm on Tuesday, April 15. Exam 2 will be very similar to a problem set except that you will be required to do all exam work completely on your own without any help from another person. The material covered by the exam will be all lectures through Lec #18 (the second iteration lecture on Thursday April 3), all labs through Lab 9 (the iteration lab), and all problem sets through Problem Set 8 (the iteration problem set). We will do our best to grade your PS8 as soon as possible and will post PS8 solutions soon after the PS8 deadline.

Reading

  • IntListList Contract
  • Study the code in the file IntFunctions.java within the lec18_iteration folder.
  • Study the code in the file IntListFunctions.java within the lec18_iteration folder.
  • Study the code in the file IntListListFunctions.java within the lec18_iteration folder.
  • About this Problem Set

    The purpose of this problem set is to give you experience with iteration (tail recursion, while loops, and for loops) and list of lists. In Task 1, you will use list of lists to determine all the different ways to make change for a given amount of money. In Task 2, you will use iteration to manipulate lists. In Task 3 you will use iteration to create pictures of nested boxes.

    All code for this assignment is available in the ps8_programs folder in the cs111d download directory on puma.

    How to turn in this Problem Set

    You are required to turn in both a hardcopy and a softcopy. For general guidelines on problem set submission, including how to submit a softcopy and how to check if you softcopy submission was successful, click here. Please make sure to keep a copy of your work, either on a zip disk, or in your private directory (or, to play it safe, both).

    Hardcopy Submission

    Your hardcopy packet should consist of:
    1. The cover page;
    2. Your modified ChangeMaker.java file from Task 1.
    3. Your iteration table from Task 2a;
    4. Your modified Partition.java file from Tasks 2b, 2c, 2d, and 2e;
    5. Your iteration table from Task 3a;
    6. Your modified NestedFrames.java file from Task 3b;
    Staple these together, and slide the packet under the door of Elena's office (E127, in minifocus).

    Softcopy Submission

    You should submit your final version of your ps8_programs folder. In particular,

    Task 1: Making Change

    Lists of lists are useful data structures for holding lists of possibilities. We can use them to hold the list of all subsets of a set of numbers like we saw in lecture. We could also use them to hold a list of all permutations of a list of numbers, using an approach similar to computation of string permutations considered in the previous problem set. In this problem, we will use lists of lists to represent all the possible ways of making change for a given amount of money given an unlimited number of coins with certain denominations. Some examples are given below (assume all values are in cents).

    Amount to change Denominations Ways to Make Change
    5 [5,1]
    [[5],            // 1 nickel
     [1, 1, 1, 1, 1] // 5 pennies
     ]
    16 [10,5,1]
    [[10, 5, 1],               // 1 dime, 1 nickel, and 1 penny
     [10, 1, 1, 1, 1, 1, 1],   // 1 dime and 10 pennies
     [5, 5, 5, 1],             // 3 nickels and 1 penny
     [5, 5, 1, 1, 1, 1, 1, 1], // 2 nickels and 6 pennies
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 1 nickel and 11 pennies
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] // 16 pennies.
     ]

    Your goal is to formulate a strategy that will list all the possible ways to make change for a given amount of money with a list of possible coin denominations provided in descending order of value. You will be completing the method makeChange of the ChangeMaker class. The skeleton for the method is provided below:

    public static IntListList makeChange (int amount, IntList coins)
    Returns a list of possible ways to make change for amount using the coin denominations in the list coins. Assume the integers in coins are in descending order of value.

    Complete this problem by fleshing out the definition of makeChange in the ChangeMaker.java file within the ChangeMaker folder.

    Notes

    Correct Test Case Answers

    
    ----------------------------------------------------
    There are 1 ways to make change for 5 cents using [5]:
    [[5]
     ]
    ----------------------------------------------------
    There are 1 ways to make change for 5 cents using [10, 5]:
    [[5]
     ]
    ----------------------------------------------------
    There are 1 ways to make change for 10 cents using [5]:
    [[5, 5]
     ]
    ----------------------------------------------------
    There are 2 ways to make change for 10 cents using [10, 5]:
    [[10],
     [5, 5]
     ]
    ----------------------------------------------------
    There are 1 ways to make change for 15 cents using [5]:
    [[5, 5, 5]
     ]
    ----------------------------------------------------
    There are 2 ways to make change for 15 cents using [10, 5]:
    [[10, 5],
     [5, 5, 5]
     ]
    ----------------------------------------------------
    There are 0 ways to make change for 16 cents using [10, 5]:
    []
    ----------------------------------------------------
    There are 2 ways to make change for 5 cents using [5, 1]:
    [[5],
     [1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 3 ways to make change for 10 cents using [5, 1]:
    [[5, 5],
     [5, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 4 ways to make change for 10 cents using [10, 5, 1]:
    [[10],
     [5, 5],
     [5, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 4 ways to make change for 15 cents using [5, 1]:
    [[5, 5, 5],
     [5, 5, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 6 ways to make change for 15 cents using [10, 5, 1]:
    [[10, 5],
     [10, 1, 1, 1, 1, 1],
     [5, 5, 5],
     [5, 5, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 6 ways to make change for 16 cents using [10, 5, 1]:
    [[10, 5, 1],
     [10, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 1],
     [5, 5, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 13 ways to make change for 26 cents using [25, 10, 5, 1]:
    [[25, 1],
     [10, 10, 5, 1],
     [10, 10, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 1],
     [10, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 1],
     [5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    ----------------------------------------------------
    There are 60 ways to make change for 56 cents using [25, 10, 5, 1]:
    [[25, 25, 5, 1],
     [25, 25, 1, 1, 1, 1, 1, 1],
     [25, 10, 10, 10, 1],
     [25, 10, 10, 5, 5, 1],
     [25, 10, 10, 5, 1, 1, 1, 1, 1, 1],
     [25, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 10, 5, 5, 5, 5, 1],
     [25, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [25, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 5, 5, 5, 5, 1],
     [25, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 10, 5, 1],
     [10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 5, 5, 5, 1],
     [10, 10, 10, 10, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 5, 5, 5, 5, 1],
     [10, 10, 10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 5, 5, 5, 5, 1],
     [10, 10, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1],
     [10, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
     ]
    

    Task 2: List Partitioning

    The following partitionIter method takes an integer named pivot and a list of integers named L and partitions the list into two lists:

    1. All the elements in L less than pivot.
    2. All the elements in L greater than or equal to pivot.

    The two resulting lists are returned in a two-element IntListList -- i.e., a list of two integer lists.

        public static IntListList partitionIter (int pivot, IntList L) {
          return partitionTail(pivot, L, IL.empty(), IL.empty());
        }
    
        public static IntListList partitionTail (int pivot, IntList list, 
                                                 IntList lesses, IntList greaters) {
          if (IL.isEmpty(list)) {
            return twoLists(lesses, greaters);
          } else if (IL.head(list) < pivot) {
            return partitionTail(pivot, IL.tail(list), 
                                 IL.prepend(IL.head(list), lesses), greaters);
          } else {
            return partitionTail(pivot, IL.tail(list), 
                                 lesses, IL.prepend(IL.head(list), greaters));
          }
        }
    

    Because the program manipulates both IntList and IntListList objects, it is necessary to distinguish the list operations for these different kinds of lists. As in Task 1, we will use IL. to prefix IntList operations and ILL. to prefix IntListList operations. To make the code more readable, we use the following helper method:

        public static IntListList twoLists (IntList L1, IntList L2) {
          return ILL.prepend(L1, ILL.prepend(L2, ILL.empty()));
        }
    

    Task 2a: Iteration Table

    The partitionTail method is a tail recursive method that specifies an iteration in four state variables named pivot, list, lesses, and greaters. Any iteration can be characterized by how the values of the state variables change over time. Below is a table with four columns, one for each state variable of the iteration described by partitionTail. Each row represents the values of the parameters to a particular invocation of partitionTail.

    pivotlist lessesgreaters
         
         
         
         
         
         
         
         
         

    Suppose that the list A has the printed representation [7,2,3,5,8,6,1]. Fill in the above table to show the parameters passed to successive calls to partitionTail in the computation that begins with the invocation partitionIter(5, A). There are more rows shown here than you need, so you should draw only as many rows as you need to in your table.

    Part 2b: partitionWhile

    It is possible to express any iteration as a while loop. Flesh out the following code skeleton of a partitionWhile method that behaves just like the above partitionIter method except that it uses a while loop rather than tail recursion to express the same iteration as partitionTail.

    public static IntListList partitionWhile (int pivot, IntList L) {
      // Replace this stub
      return ILL.empty();
    }
    

    Notes:

    Task 2c: partitionFor

    The iteration expressed by partitionTail and partitionWhile can also be expressed via a for loop whose index variable is the list state variable. Flesh out the skeleton of the following method so that it expresses the partitioning iteration with a for loop:

    public static IntListList partitionFor (int pivot, IntList L) {
      // Replace this stub
      return ILL.empty();
    }
    

    Recall that a Java while loop has the syntax

    for (init-statement; test-expression; update-statement) {
      body-statements
    }
    

    The above for loop is equivalent to the following while loop:

    init-statement;
    while (test-expression) {
      body-statements;
      update-statement;
    }

    Task 2d: partitionRec

    In the above partitionIter method, elements in the two returned lists are in a relative order opposite to their relative order in the original lists. For instance, partitioning the list [1, 4, 8, 3, 6, 7, 5, 2] about the pivot 6 yields the lists [2, 3, 4, 1] and [7, 6, 8].

    Suppose that we want the resulting lists to have the same relative order as in the original list. If we are provided with an IntList reversal method IL.reverse, we can easily accomplish this by reversing the two lists before gluing them together. That is, we can change the line

    	return twoLists(lesses, greaters);
    
    within partitionTail to be
    	return twoLists(IL.reverse(lesses), IL.reverse(greaters));
    

    An alternative to using IL.reverse to achieve this behavior is to define a non-tail-recursive version of partitionIter that we will call partitionRec. Flesh out the following skeleton of partitionRec, which partitions the elements of a list about the pivot but maintains the relative order of the elements in the resulting lists:

     
        public static IntListList partitionRec (int pivot, IntList L) { 
          if (IL.isEmpty(L)) { 
            return twoLists(IL.empty(), IL.empty()); 
          } else { 
            IntListList subresult = partitionRec(pivot, IL.tail(L)); 
            // replace the following stub:
            return ILL.empty(); 
          } 
        } 
    

    Notes:

    Task 2e: quicksort

    An important use of a partitioning method is a sorting algorithm known as quicksort. Here is the idea behind quicksort:
    To sort the elements of a list, partition the elements of the tail of the list around its head into result lists that we'll call lesses and greaters. Then result of sorting the whole list can be obtained by appending the result of sorting lesses to the result of prepending the head of the list to the result of sorting greaters.

    For example, if the initial list is [5, 2, 8, 3, 6, 7, 1, 4], then partitioning the tail of the list around the head (5) yields:

    	lesses = [4, 1, 3, 2]
    	greaters = [7, 6, 8]
    

    By wishful thinking, sorting lesses will yield [1, 2, 3, 4] and sorting greaters will yield [6, 7, 8]. The result of sorting the original list is the result of appending [1, 2, 3, 4] to the result of prepending 5 to [6, 7, 8].

    Flesh out a method with header public static IntList quicksort (IntList L) that uses this idea to sort the elements of a list. You may use IL.append to append two lists and any of the above partitioning methods to partition a list. The quicksort method is tested by the main method of the Partition class.

    It turns out that quicksort, true to its name, is one of the fastest algorithms for sorting a list. If you take CS230 and CS231, you will learn (among other things) much more about various sorting algorithms and how to compare them in terms of efficiency.


    Task 3: Nested Frames

    In this problem you will use iteration in to draw two-colored nested frame patterns like those shown below:

    Each of the four patterns consists of concentric rectangular frames that have the same thickness and alternate between two colors. In the above example, each target has 10 nested frames, each of whose thicknesses is 1/20 of the dimensions allocated to the pattern. (When the thickness is 1/(2*nestingLevels), the frames will evenly fill the alloted Picture space)

    In Picture World, each rectangular frame pattern can be drawn as a sequence of concentric filled rectangles, where the rectangles are draw from the outside in. You have been provided with the following method for creating a centered rectangular picture:

    public Picture centeredRect (double fraction, Color c)
    Returns a rectangle filled with color c that is centered in the picture canvas in which it is drawn. The width and height of the rectangle are each the given fraction of the enclosing picture canvas's width and height. The fraction argument must be between 0 and 1.

    For example, using this method, here is a recursive implementation of the nested frame pattern:

    public Picture nestedRec(int level, double thickness, Color c1, Color c2) {
      if (level == 0) {
        return empty();
      } else {
        return overlay(nestedRec(level - 1, thickness, c2, c1),
                       centeredRect(2*level*thickness, c1));
      }
    }

    Here, level is the number of nested frames, thickness represents the thickness of each frame edge as a fraction of the dimensions allocated to the pattern, c1 is the outermost color, and c2 is the color that alternates with c1. In the code that you are given, when nestedRec is initially invoked, the thickness argument is initially 1/(2 * initlevel), where initlevel is the initial level number. The nestedRec method accumulates a final picture that consists of level centered rectangles overlayed on top of one another. Note how each level of the recursion decrements level by 1 and swaps c1 and c2 (so that c2 is the outermost color in the nested subpicture). This strategy is not a tail recursive one, since there is still a pending overlay operation to be performed after the recursion returns.

    In the rest of this problem, you will expore three iterative strategies for expressing the nested box pattern. You will start by creating an iteration table for the nested boxes.

    Task 3a: Iteration Table

    Create an iteration table for creating the nested frame picture with iteration. The table should have a column for each of the state variables in the iteration. These include the four parameters (level, thickness, c1, and c2) as well as a Picture variable that contains the "answer so far" for the current iteration state. You may also want to include an extra column that contains the picture that will be used in combination with the current answer to generate the next answer in the next row of the iteration table. This extra column should have pictures that can be created from the other state variables and the Picture methods that are available to you (including centeredRect). Draw your iteration table for a process that produces the same picture as the following invocation, but does so in an iterative manner than a non-tail-recursive one:

    nestedRec(4,0.125,Color.blue,Color.green);
    
    Turn this in with the hardcopy of your assignment.

    Task 3b: Iterative Methods

    For the rest of this problem, you will be fleshing out the following skeletons in the file NestedFrames.java within the folder NestedFrames in the ps8_programs folder:
    public Picture nestedIter(int n, double thickness, Color c1, Color c2) {
      // This method contains the initial call to nestedTail, which does all the work.
      return nestedTail(n, thickness, c1, c2, empty());
    }
    	
    public Picture nestedTail(int n, double thickness, 
                              Color c1, Color c2, Picture ans) {
      // nestedTail should be a tail recursive method that returns a Picture 
      // that is the nested frames pattern. 
    
      // Replace the following stub by a correct definition.
      return empty();
    }
    	
    public Picture nestedWhile(int n, double thickness, Color c1, Color c2) {
      // Use a while loop to accumulate and return a Picture 
      // that is the nested frames pattern.
    
      // Replace the following stub by a correct definition.
      return empty();
    }
    	
    public Picture nestedFor(int n, double thickness, Color c1, Color c2) {
      // Use a for loop to accumulate and return a Picture 
      // that is the nested frames pattern.
    
      // Replace the following stub by a correct definition.
      return empty();
    }
    

    Your task is to flesh out the three methods nestedTail, nestedWhile, and nestedFor so that they yield the same picture as nestedRec, but do so via the iterative process exemplified in your iteration table from Part a. You can test your methods by executing the NestedFrames.html applet. This will give you a window like that displayed at the beginning of this problem. By selecting an integer in the rightmost choice box, you can change the nesting level of the patterns. Your code does not have to take care of calculating the initial thickness; this calculation is already performed by the testing enviroment.

    The patterns are arranged as follows inside the NestedFrames Applet window:

    In your definitions, pay attention to the following notes: