Problem #1
Preorder traversal 2, 6, 0, 1, 3, 5, 7, 9, 8, 4
Inorder traversal 0, 6, 3, 1, 5, 2, 7, 8, 9, 4
Postorder traversal 0, 3, 5, 1, 6, 8, 4, 9, 7, 2
2 points each, only partial credit is if the sequence matches the right answer
other than one single error (missing number, wrong number, transposed pair)
problem #2
solutions
public void printTwos(int n) {
if (n < 1)
throw new IllegalArgumentException();
else if (n % 4 == 0) {
System.out.print("2 * ");
printTwos(n / 4);
System.out.print(" * 2");
} else if (n % 2 == 0) {
System.out.print("2 * ");
printTwos(n / 2);
} else {
System.out.print(n);
}
}
public static void printTwos(int n) {
if (n < 1)
throw new IllegalArgumentException();
printTwos(n, 0);
}
public static void printTwos(int n, int numPrinted) {
if (n % 2 != 0)
System.out.print(n);
else if (numPrinted % 2 == 0) {
System.out.print("2 * ");
printTwos(n / 2, numPrinted + 1);
} else {
printTwos(n / 2, numPrinted + 1);
System.out.print(" * 2");
}
}
1 correct header
1 correct exception
2 base case for odd numbers
1 test for this case or test for 1 (could be an else with a test for even)
1 print n in this case (println is okay here)
5 recursive cases
1 a recursive case testing n%2==0 or n%4==0 and recursing on n/2 or n/4
1 a 2nd recursive case testing n%2==0 or n%4==0 and recursing on n/2 or n/4
1 correctly prints 2 * recurse(n/4) * 2 when n%4==0
2 correctly prints 2 * recurse(n/2) when n%2==0 && n%4!=0 (n/2 % 2 != 0)
(-1 if test is incomplete, e.g., testing n % 2 == 0)
notes:
-1 if they use println but only if they got some printing correctness point
-1 if they include a call on printTwos in a println but only if they got some
recursive case correctness points
Problem #3
Statement Output
------------------------------------------------------------
var1.method2(); Pig 2
var2.method2(); Dog 2
var3.method2(); Dog 2
var4.method2(); compiler error
var5.method2(); Horse 2
var6.method2(); Pig 2
var1.method3(); Cat 3/Pig 2
var2.method3(); compiler error
var3.method3(); compiler error
var4.method3(); compiler error
var5.method3(); Cat 3/Horse 2
var6.method3(); Cat 3/Pig 2
((Pig)var5).method1(); runtime error
((Cat)var3).method3(); Cat 3/Dog 2
((Cat)var4).method1(); compiler error
((Pig)var1).method1(); Horse 1/Dog 2
((Horse)var4).method1(); Horse 1/Dog 2
((Cat)var2).method3(); runtime error
((Horse)var3).method1(); runtime error
((Dog)var4).method2(); Horse 2
Problem #4
solution
public static boolean isSorted(Stack s) {
if (s.size() <= 1)
return true;
else {
Queue q = new LinkedList();
int prev = s.pop();
q.add(prev);
boolean ok = true;
while (!s.isEmpty()) {
int next = s.pop();
if (prev < next)
ok = false;
q.add(next);
prev = next;
}
while (!q.isEmpty())
s.push(q.remove());
while (!s.isEmpty())
q.add(s.pop());
while (!q.isEmpty())
s.push(q.remove());
return ok;
}
}
1 header
1 constructs temporary queue using generics correctly
1 special test for size < 2 or equivalent
1 basic idea: S -> Q, Q -> S, comparing adjacent values
-------------------------------------------------------------------------------
no more points if student doesn't have basic idea
2 four loops to get correct order: S -> Q, Q -> S, S-> Q, Q -> S
1 attempt
1 correct (can get this even if they return early)
1 compare adjacent values correctly (all pairs, correct order)
2 restores stack in all cases (normally lose this if they return early)
1 attempt (flag or code to restore before returning)
1 correct
1 always returns appropriate values (flag or true/false)
Problem #5
solution
public void printLeaves() {
if (overallRoot == null)
System.out.println("no leaves");
else {
System.out.print("leaves:");
printLeaves(overallRoot);
System.out.println();
}
}
private void printLeaves(IntTreeNode root) {
if (root != null)
if (root.left == null && root.right == null)
System.out.print(" " + root.data);
else {
printLeaves(root.right);
printLeaves(root.left);
}
}
1 overall setup: correct public/private headers, public method passes
overallRoot to private method
1 prints "no leaves" when overallRoot is null and in no other cases (don't
worry about print versus println for this point)
1 base case for null (tests for this and prevents any NullPointerException)
3 handles leaf nodes properly
1 reasonable attempt to test for this case
1 prints root data for some leaves (ignore spacing, requires test attempt)
1 prints root data for all leaves and just leaves with spaces
3 recursive calls on left and right
1 reasonable attempt (some kind of recursive call on left or right)
1 correctly traverses the entire tree
1 traverses right-to-left
1 other formatting details correct (prints "leaves:" before call, each call
produces exactly one line of output)
Problem #6
solution
public static Map> convert(Set numbers) {
Map> result = new TreeMap>();
for (String s : numbers) {
String exchange = s.substring(0, 3);
String digits = s.substring(4);
if (!result.containsKey(exchange)) {
result.put(exchange, new TreeSet());
}
result.get(exchange).add(digits);
}
return result;
}
1 header
2 construct and return proper map
1 reasonable attempt: map of strings to sets
1 all correct (correct generics, correct return, map is a TreeMap, must
have () in call to new)
1 loop over set
1 properly split the string (s.split("-") okay)
3 add a new set to map when key is first seen
1 reasonable attempt to test for this case
1 reasonable attempt to construct new set in this case
1 all correct (correct generics, set is TreeSet, () in call to new,
efficient--constructs sets only in this case)
2 adds suffix to existing set assuming key is there
1 reasonable attempt (getting something from the map that they then add to)
1 all correct
notes:
if they are missing () in call to new, don't take it off twice
Problem #7
solution
public class FoodData implements Comparable {
private String name;
private double fat;
private double carbs;
private double protein;
public FoodData(String name, double fat, double carbs,
double protein) {
if (fat < 0 || carbs < 0 || protein < 0)
throw new IllegalArgumentException();
this.name = name;
this.fat = fat;
this.carbs = carbs;
this.protein = protein;
}
public String getName() {
return name;
}
public double getCalories() {
return 9 * fat + 4 * (carbs + protein);
}
public double percentFat() {
return 100.0 * (9 * fat / getCalories());
}
public String toString() {
return name + ": " + fat + "g fat, " + carbs +
"g carbohydrates, " + protein + "g protein";
}
public int compareTo(FoodData other) {
double difference = percentFat() - other.percentFat();
if (difference < 0)
return -1;
else if (difference > 0)
return 1;
else
return name.compareTo(other.name);
}
}
1 class header
2 fields (0.5 points each but round up, -1 if not private, okay to have extra
field(s) for calories or fat calories or percent fat)
2 constructor
1 exception
1 correct header and sets four fields correctly
1 getName correct
3 getCalories and percentFat correct
1 reasonable attempt at getCalories
1 reasonable attempt at percentFat
1 both correct (ignore case where getCalories() == 0)
2 toString correct
1 includes all four fields
1 correct format
4 compareTo
1 primary comparison is for some kind of fat comparison
1 correctly computes difference of percent fat and returns int (using
if/else or (int)Math.signum; hard to get this unless they make calls on
percentFat)
1 puts lower percent fat first
1 all other aspects correct (header, alphabetical name comparison when
percentFat equal)
Notes:
ignore any code for rounding
Problem #8
solution
public void makeFull() {
overallRoot = makeFull(overallRoot);
}
private IntTreeNode makeFull(IntTreeNode root) {
if (root != null) {
root.left = makeFull(root.left);
root.right = makeFull(root.right);
if (root.left == null && root.right != null)
root = root.right;
else if (root.left != null && root.right == null)
root = root.left;
}
return root;
}
1 overall setup: public/private headers (private needs root), public calls
private passing overallRoot
2 root == null case
1 attempt
1 correct
2 Eliminating 1-child nodes
1 reasonable attempt for one of the two 1-child cases
1 correctly resets root for both 1-child cases
STOP HERE if they don't get 1-child node attempt (don't be shy about asking
question leader if something qualifies as attempt)
5 x = change(x) used correctly
1 return type for private method
1 return root in private
1 overallRoot = makeFull(overallRoot)
1 root.left = makeFull(root.left)--all such calls
1 root.right = makeFull(root.right)--all such calls
1 2-child case works (recursive calls)
1 leaf case works (unchanged)--requires tests
3 recursive calls are made for 1-child cases
1 exist
2 before assignment or as part of assignment (root = makeFull(root.left))
Problem #9
solutions
public void reverse3() {
if (front != null && front.next != null &&
front.next.next != null) {
ListNode temp = front;
front = front.next.next;
ListNode temp2 = front.next;
front.next = temp.next;
temp.next.next = temp;
temp.next = temp2;
while (temp.next != null && temp.next.next != null &&
temp.next.next.next != null) {
temp2 = temp.next;
temp.next = temp.next.next.next;
temp = temp2;
temp2 = temp.next.next.next;
temp.next.next.next = temp.next;
temp.next.next = temp;
temp.next = temp2;
}
}
}
public void reverse3() {
front = reverse3(front);
}
private ListNode reverse3(ListNode lst) {
if (lst != null && lst.next != null && lst.next.next != null) {
ListNode temp = lst;
lst = lst.next.next;
ListNode temp2 = lst.next;
lst.next = temp.next;
temp.next.next = temp;
temp.next = temp2;
temp.next = reverse3(temp.next);
}
return lst;
}
1 header
2 generous pattern matching
1 attempt to rearrange links for first 3 values:
requires resetting front
requires resetting at least two ".next" fields
normally comes before loop
1 attempt at a loop to rearrange links for later sequences (or recursive
equivalent):
requires a current, test on current or current... becoming null
requires resetting at least two ".next" fields
3 Simple cases
1 works (does nothing) for empty list (requires test)
1 works (does nothing) for 1-element list (requires test)
1 works (does nothing) for 2-element (requires test)
7 Works for specific cases (if you think they have a bug that is not caught by
the test cases, ask the question leader what points to deduct)
1 3-element list
1 4-element list
1 5-element list
1 6-element list (0.5 pt if just first triple is bad)
1 7-element list (0.5 pt if just first triple is bad)
1 9-element list (0.5 pt if just first triple is bad)
1 11-element list (0.5 pt if just first triple is bad)
We have a general rule that if you can fix one problem and it suddenly works,
then we make that fix and charge them 4 points. If this gives someone a higher
score, you can grade it that way. But don't spend too much time trying to
figure out their mistakes.
Stuart Reges
Last modified: Fri Sep 16 16:16:07 PDT 2011