Final Exam Review Problems - Computer Programming & Problem Solving | CS 111, Study notes of Computer Science

Material Type: Notes; Class: LAB:Comp Program & Prob Solv; Subject: Computer Science; University: Wellesley College; Term: Spring 2003;

Typology: Study notes

Pre 2010

Uploaded on 08/18/2009

koofers-user-a05
koofers-user-a05 🇺🇸

5

(1)

8 documents

1 / 18

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
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.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12

Partial preview of the text

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