Download Final Exam Review Problems - Computer Programming & Problem Solving | CS 111 and more Study notes Computer Science in PDF only on Docsity!
Wellesley College ◊ CS111 Computer Programming and Problem Solving ◊ Spring 2003
FINAL EXAM REVIEW PROBLEMS
The CS111 final exam is a self-scheduled exam held during the normal final exam period. It is an
open book exam: you may refer to any books, notes, and assignments. You may not talk to other
people about the exam before or after taking it (including students who took CS111 in previous
semesters), nor may you use a computer during the exam.
Here is a list of topics covered by the course that may be tested on the final exam:
- problem solving patterns: divide/conquer/glue, recursion, iteration (tail recursion, while
loops, for loops);
- abstraction: method abstraction, data abstraction, abstraction barriers/contracts/APIs.
- modularity: constructing programs out of mix and match parts (e.g. generators, mappers,
filters, accumulators) that use standard interfaces (lists, arrays).
- control structures: sequencing, method invocation, conditionals ( if / else ), loops
( while , for ), return.
- data structures: objects, lists, arrays, strings, sets (e.g. StringSet).
- models: execution diagrams, invocation trees, object diagrams, box-and-pointer-diagrams for
lists, inheritance hierarchies.
- Java methods: declaration vs. invocation; parameter declaration and use; formal vs. actual
parameters; scope of parameter names; void vs. non- void return types; using return to
return result; invocation model (create a frame in Java execution model).
- Java class declarations: instance variables, class (static) variables; constructor methods,
instance methods, class (static) methods; inheritance.
- Java statements: local variable declarations, method invocations, assignments, if / else
conditionals, while loops, for loops, return ; security keywords ( public , protected ,
private )
- Java expressions: literals (numbers, booleans, characters, strings), variable references
(instance variables [e.g., foo.x], array subscripts [e.g., foo[i]], this , super ), constructor
method invocations ( new ), array creation expressions (e.g. new int[3] and new int []
{7,3,2} ), non- void method invocations, primitive operator applications (arithmetic,
relational, logical).
- microworlds: BuggleWorld, TurtleWorld, PictureWorld, ListWorld, Java Graphics,
AnimationWorld.
Below are some problems intended to help you review material for the final exam. The problems do
not cover all of the topics listed above, so you should also review your notes and assignments.
The problems range in difficulty. Some problems are from previous final exams. Others (with some
rewriting) could be turned into reasonable final exam problems. Others are too long or complex for a
final exam problem, but review material that is covered on the exam.
The problems are not in any particular order, so you should not feel compelled to do them in order.
Rather, you should first work on those problems that cover material in which you think you need the
most practice. To help you decide which problems to work on, each problem lists the concepts that
the problem covers.
There is a handout of solutions that accompanies this collection of problems.
____________________________________________________________________________
Problem 1: Sales Statistics (Data Abstraction, Arrays, Lists, Objects, Object Diagrams)
The management of the Decelerate Clothing Store (specializing in "clothes that slow you down") wants to
track certain statistics about customer purchases. In particular, they want to track the amount of each
purchase and whether it was made with cash or credit card. Later, they want to be able to calculate statistics
based on this information, such as the largest cash purchase amount, the average amount of a credit card
purchase, and the percentage of credit card purchases.
The management has hired Abby Stracksen of Simplistic Statistics to implement a Java program for
tracking the purchase information and calculating the desired statistics. Abby begins by designing a contract
for a History class that maintains a history of customer purchase:
Contract for the History Class
Constructor method for the History class
public History ( int maxEntries);
Returns a new History object that can store up to maxEntries purchase entries.
Instance methods for the History class
public void add ( int amount, boolean cash);
Adds a new purchase entry to this history: amount is the amount of the purchase; cash
value true indicates a cash purchase, cash value false indicates a credit card purchase.
An attempt to add an entry is ignored if maxEntries entries have been stored.
public int size ();
Returns the number of entries in this history.
public int min ( boolean cash);
Returns the minimum amount of a purchase made with the given cash value.
I.e. if cash is true, return the minimum purchase made with cash, otherwise return the
minimum purchase made with credit card. If there are no purchases with the given cash
value, returns the largest integer.
public int max ( boolean cash);
Returns the maximum amount of a purchase made with the given cash value. If there are
no purchases with the given cash value, returns the smallest integer.
public int average ( boolean cash);
Returns the average amount of a purchase made with the given cash value. If there are
no purchases with the given cash value, returns 0.
public int number ( boolean cash);
Returns the number of purchases made with the given cash value.
public double percentage ( boolean cash);
Returns the percentage (by number of purchases) of all purchases made with the given
cash value. Returns 0 if there have been no purchases.
public class History {
// Instance Variables: private Purchase [ ] purchases; private int size;
// Constructor Method: public History ( int maxEntries) { purchases = new Purchase[maxEntries]; size = 0; }
// Instance Methods: public void add ( int amount, boolean cash) { if (size < purchases.length) { purchases[size] = new Purchase(amount, cash); size = size + 1; } }
// I still need to finish the other methods! - Emil - }
Part a. Based on Emil's implementation, draw an object diagram that shows the result of executing
the following statements. Your diagram should include the local variable h and all objects that are
accessible from h via some sequence of pointers.
History h = new History(5); h.add(82, false); // credit purchase h.add(53, true); // cash purchase h.add(178, false); // credit purchase
Part b. Finish Emil's implementation by fleshing out the missing instance methods from his
History class.
Part c. Your colleague Bud Lojack believes that Emil could also have written the constructor
method for Purchase in either of the two ways below:
public Purchase ( int amount, boolean cash) { amount = amount; cash = cash; }
public Purchase ( int a, boolean c) { int amount = a; int cash = c; }
Is Bud right? Explain.
Part d. On his desk, Emil left the following notes about alternative implementations of the
Purchase class:
Many ways to implement Purchase instance. E.g.
1) As an array of two integers. Slot 0 = amount; Slot 1 = cash (use 0 for false, 1 for true).
2) As an integer list with two elements. First element = amount; second = cash (use 0 for
false, 1 for true)
3) As a single positive/negative integer. Amount is the absolute value. Positive indicates
cash; negative indicates credit.
4) As a single positive integer n. Amount = n / 2; cash = n % 2, where 0 is false, 1 is true.
Based on Emil's notes, provide four alternative implementations of the Purchase class that all
satisfy the Purchase contract.
Part e. Bud Lojack thinks that Emil should have made the amount and cash instance variables of the
Purchase class public rather than private. Explain to Bud why this is a bad idea.
Part f. Emil returns from his trip, and says that he had an epiphany about an alternative
representation of History instances that does not involve Purchase objects. Instead, Emil thinks a
history instance can be implemented as an object with three instance variables:
1. The maxEntries integer.
2. An integer list cashes holding the amounts of the cash purchases.
3. An integer list credits holding the amounts of the credit purchases.
i. Repeat part (a) using this representation of the History class.
ii. Write an alternative implementation of the History class based on this representation.
Part g. The implementations of the History class considered above are only two of many possible
implementations. What are some other implementations? For each implementation you can think of,
draw an object diagram of the example from part (a).
Part c. Write the following PictureWorld method:
public Picture squares ( int n, Color c1, Color c2)
Returns a picture with n adjacent squares sitting at the bottom of the frame. The leftmost square
should fill the lower left quadrant of the frame. Each subsequent square should be one-half the
size of the square to its left. The colors of the squares should alternate between c1 and c2 from
left to right. Assume that public Picture patch (Color c) returns a rectangular picture with
color c that fills whole frame.
Part d. Write the following instance method squares() for a SquareCanvas subclass of Canvas.
public void squares (Graphics g, int n, int len, Color c1, Color c2)
Draws in this canvas a picture with n adjacent colored squares as shown below. The leftmost
square has side length len and an upper left corner at (0,0). Each successive square has a side
length that is half the side length of the square to its left. The colors of the squares should
alternate between c1 and c2 from left to right.
________________________________________________________________________________
Problem 3: Greatest Common Divisor (Iteration)
Wyla Lupe has been experimenting with ways to calculate the greatest common divisor (GCD) of
two integers. The GCD of two integers A and B is the largest integer that evenly divides into both A
and B. For example, the GCD of 30 and 18 is 6, the GCD of 28 and 16 is 4, and the GCD of 17 and
11 is 1.
A clever algorithm for computing GCDs was developed by Euclid in 300 B.C. (In fact, it is
considered by many to be the oldest non-trivial algorithm!) Wyla has expressed Euclid's algorithm
in Java as the following tail recursive GCDTail method. (You do not have to understand why the
algorithm works!)
public static int GCDTail( int A, int B) { if (B == 0) { return A; } else { return GCDTail(B, A % B); } }
Recall that A % B (pronounced "A mod B") calculates the remainder of A divided by B. For example,
10%3 is 1 , 10%4 is 2 , 10%5 is 0 , and 10%6 is 4.
Part a In the following table, show the sequence of values that the parameters A and B take on in the
iterative calculation of GCDTail(95,60). Important: You have been provided with more rows than
you need, so some rows should remain empty when you are done.
A B
Part b. In the following GCDWhile code skeleton, implement an alternative version of Euclid's GCD
algorithm that uses a while loop to express the same iteration that is expressed by Wyla's GCDTail
method. You may wish to introduce one or more local variables.
public static int GCDWhile ( int A, int B) { // Flesh out this skeleton
Part c. Would it be easy to re-express Wyla's GCDTail program as a for loop? Briefly explain your
answer.
________________________________________________________________________________
Problem 5: Inversions (Arrays, Iteration, Lists)
In an integer array A, an inversion is defined to be a pair of indices (i, j) such that i < j and A[i] > A[j]. For
instance, the following array s has five inversions: (0, 1), (0, 4), (2, 3), (2, 4), and (3, 4).
s (^36 1751 )
Part a. Implement the following method:
public static int countInversions ( int [] a);
Returns the number of inversions in a.
For instance, countInversions(s) should return 5.
Part b. Implement the following method:
public static PointList listInversions ( int [] a);
Returns a list of all the inversions in a. Each inversion (i, j) should be represented as a Point instance
whose x field is i and y field is j. The order of inversions in the resulting list is immaterial.
You may assume PointList is like IntList, except stores a list of Points rather than ints. For instance,
System.out.println(listInversions(s)) might (among many possible orderings) display:
[java.awt.Point[x=3,y=4], java.awt.Point[x=2,y=4], java.awt.Point[x=2,y=3], java.awt.Point[x=0,y=4],java.awt.Point[x=0,y=1]]
________________________________________________________________________________
Problem 6: Inheritance (Inheritance)
Consider the following five simple classes
class A { public int m1() { return 1;} public int m2() { return m3();} public int m3() { return 2;} } class B extends A { public int m1() { return m2();} public int m3() { return 3;} }
class D extends A { public int m1() { return super .m2();} public int m3() { return 5;} } class C extends B { public int m2() { return 4;} }
class E extends D { public int m2() { return 6;} }
What is printed in the stdout window when the following statements are executed?
System.out.println(( new A()).m1()); System.out.println(( new B()).m1()); System.out.println(( new C()).m1()); System.out.println(( new D()).m1()); System.out.println(( new E()).m1());
________________________________________________________________________________
Problem 7: Converting Betweeen Different Forms of Iteration (Lists, Arrays, Iteration)
We saw in class that iterations could be expressed as tail recursions, while loops, and for loops. Each of
the following parts contains a method that uses one of these forms of iteration. For each part, write two
equivalent methods that use the other two forms of iteration.
Part a.
public static int weightedSum (IntList L) { return weightedSumTail (L, 1, 0); }
public static int weightedSumTail (IntList L, int index, int total) { if (isEmpty(L)) { return total; } else { return weightedSumTail(tail(L), index + 1, (index*head(L)) + total); } }
Part b.
public static boolean isMember ( int n, int [] a) { int i = a.length - 1; while ((i >= 0) && (a[i] != n)) { i = i - 1; } return (i >= 0); // Will only be true if n is in a. }
Part c.
public static void partialSum ( int [] a) { int sum = 0; for (int i = 0; i < a.length; i++) { sum = sum + a[i]; a[i] = sum; } }
Part d.
public static void squiggle (Graphics g, int x1, int y1, int x2, int y2) { if ((x1 > 0) || (y1 > 0) || (x2 > 0) || (y2 > 0)) { g.drawLine(x1, y1, x2, y2); squiggle(g, x2, y2, y1/4, x1*2); } }
________________________________________________________________________________
Problem 8: Converting Betweeen Arrays and Lists (Lists, Arrays, Iteration)
Implement the following two methods for converting between lists and arrays of integers:
public static int [] listToArray (IntList L);
Returns an array of integers whose length is the same as the length of L and whose elements, from
low to high index, are in the same order as the elements of L.
public static IntList arrayToList ( int [] a);
Returns a list of integers whose length is the same as the length of a and whose elements are in the
same order as the elements of a (from low to high index).
______________________________________________________________________________
Problem 10: Leftist Turtles (Tests Instance Variables, Class Declarations, Inheritance)
Suppose we want a LeftistTurtle subclass of Turtle that remembers the number of times that it has been
invoked with the lt() method. A LeftistTurtle has the same contract as Turtle except that it also understands
the following additional instance method:
public int numberOfLefts ();
Returns the number of times that the lt() method has been invoked on this turtle.
Part a. Write a complete class declaration for LeftistTurtle implementing the LeftistTurtle contract.
Part b. Consider the following test of the LeftistTurtle class:
LefistTurtle leo = new LeftistTurtle(); leo.lt(45); leo.rt(30); System.out.println(leo.numberOfLefts());
You might expect that executing the above statements should print 1, but, depending on the implementation of the
rt() method in Turtle, it might in fact print 2. Explain how this could happen.
Part c. Suppose that Turtle is implemented in such a way that the test code in Part b returns 2. Modify your
implementation of LeftistTurtle so that numberOfLefts() returns only the number of lt() method calls and
does not count the number of rt() method calls. You should only change LeftistTurtle; you should not change
Turtle!
________________________________________________________________________________
Problem 11: Bank Accounts (Data Abstraction, Lists)
Suppose that there is a Java class Account that represents bank accounts. A straightforward way to represent
a simple bank account is to keep track of three integer instance variables representing, respectively, the
savings account balance, the checking account balance and the total amount of money in the bank (equal to
the sum of the savings and checking account balances). Assume further that the constructor method for the
class Account has zero parameters. With this straightforward approach, the constructor method is
public Account ( ) { this .savings = 0; this .checking = 0; this .total = 0; }
resulting in the following object diagram representation:
total
checking
savings
Account
0
Below is a Java class that implements this straightforward representation.
class Account {
private int savings; private int checking; private int total;
public account () { this .savings = 0; this .checking = 0; this .total = 0; }
public int getSavings() { return this .savings;} public int getChecking() { return this .checking;} public int getTotal() { return this .total;}
public void depositToSavings( int amountToAdd) { this .savings = this .savings + amountToAdd; this .total = this .total + amountToAdd; }
public void transferFromSavingsToChecking( int transferAmount) { this .savings = this .savings - transferAmount; this .checking = this .checking + transferAmount; }
public void withdrawFromChecking( int withdrawalAmount) { this .checking = this .checking - withdrawalAmount; this .total = this .total - withdrawalAmount; } }
________________________________________________________________________________
Problem 12: End Moves (Lists of Lists, Iteration, Recursion)
In this problem we consider an endMoves() method that returns all ways to move an element of
an integer list to the end of the list. For example:
endMoves([]) = [] endMoves([5]) = [[5]] endMoves ([7,5]) = [[5,7], [7,5]] endMoves ([3,7,5]) = [[7,5,3], [3,5,7], [3,7,5]] endMoves ([6,3,7,5]) = [[3,7,5,6], [6,7,5,3], [6,3,5,7], [6,3,7,5]]
In this problem, you will consider several different methods that satisfy the following contract:
public static IntListList endMoves (IntList L);
Given an IntList L of n elements, return an IntListList of n elements whose i th
element is the result of moving the i th element of L to the end of L.
These methods may use the following auxiliary methods from the IntList and IntListList
classes. Class methods from the IntList class should be prefixed with IL., while those from
the IntListList class should be prefixed with ILL.
IntList methods IntListList methods
IL.isEmpty() ILL.isEmpty() IL.head() ILL.head() IL.tail() ILL.tail() IL.empty() ILL.empty() IL.prepend() ILL.prepend() IL.postpend() ILL.postpend() IL.append() ILL.append() IL.reverse() ILL.reverse() ILL.mapPrepend()
Recall that IL.postpend()/ILL.postpend() add an element to the end of a list and ILL.mapPrepend()
prepends an integer to every list in a given list of lists:
IL.postpend([6,3,7], 5) = [6,3,7,5] ILL.postpend([[],[1],[1,2]], [1,2,3]) = [[],[1],[1,2],[1,2,3]] ILL.mapPrepend(6, [[7,5,3],[3,5,7],[3,7,5]]) = [[6,7,5,3],[6,3,5,7],[6,3,7,5]]
Part a. Below is a definition of a method endMovesIter() (and its tail recursive helper method
endMovesTail()) that correctly implements the endMoves() contract:
public static IntListList endMovesIter (IntList L) { return endMovesTail (IL.empty(), L, ILL.empty()); }
public static IntListList endMovesTail (IntList left, IntList right, IntListList ans) { if (IL.isEmpty(right)) { return ans; } else { return endMovesTail (IL.postpend(left, IL.head(right)), IL.tail(right), ILL.postpend(ans, IL.append(left, IL.postpend(IL.tail(right), IL.head(right))))); } }
The endMovesTail() method is a tail recursive method that specifies an iteration in three state
variables: left, right and ans. Any iteration can be characterized by how the values of the state
variables change over time. Below is a table with three columns, one for each state variable of
the iteration described by endMovesTail(). Each row represents the values of the parameters to
a particular invocation of endMovesTail().
Suppose that the list lst has the printed representation [6, 3, 7, 5]. Fill in the following
iteration table to show the parameters passed to successive calls to endMovesTail() in the
computation that begins with the invocation endMovesIter(lst). You should write each
integer list as its printed notation (i.e., square brackets delimiting integers separated by commas)
and each list of integer lists as its printed notation (i.e., square brackets delimiting integer lists
separated by commas). You have been provided with more rows than you need, so some rows
should remain empty when you are done.
left right ans