CSE143 Key and Criteria, Fall 2008
1. Binary Tree Traversals, 6 points.
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. Binary Search Tree, 4 points.
+------------+
| Kirk |
+------------+
/ \
/ \
/ \
+------------+ +------------+
| Chekov | | Spock |
+------------+ +------------+
/ \
/ \
/ \
+------------+ +------------+
| Scotty | | Uhuru |
+------------+ +------------+
/ /
/ /
/ /
+------------+ +------------+
| McCoy | | Sulu |
+------------+ +------------+
Problem #3
Solution:
public int purebredOdds() {
return purebredOdds(overallRoot);
}
private int purebredOdds(IntTreeNode root) {
if (root == null || root.data % 2 == 0)
return 0;
else
return 1 + purebredOdds(root.left) + purebredOdds(root.right);
}
1 correct public header
1 private header with root parameter, public method returns result of calling
private with overallRoot
2 base case when root == null
1 reasonable attempt to test for this case
1 correct (returns 0 whenever root is null)
3 base case when root.data % 2 == 0
1 reasonable attempt to test for this case
2 correct (returns 0 whenever root.data is even)
3 recursive case
1 adding two recursive calls on root.left and root.right (generous)
2 correct for odds (requires reasonable attempt at testing for odd,
returns 1 + recurse(root.left) + recurse(root.right))
Problem #4
Solution:
public class AnalyzingDocumentList extends DocumentList {
private Map counts;
private int stateCount;
public AnalyzingDocumentList(int capacity) {
super(capacity);
counts = new HashMap();
counts.put(0, 1);
stateCount = 1;
}
public void add(Document d) {
super.add(d);
stateUpdate();
}
public void add(int index, Document d) {
super.add(index, d);
stateUpdate();
}
public void remove(int index) {
super.remove(index);
stateUpdate();
}
private void stateUpdate() {
stateCount++;
int size = size();
if (!counts.containsKey(size))
counts.put(size, 1);
else
counts.put(size, counts.get(size) + 1);
}
public int totalStates() {
return stateCount;
}
public int sizeCount(int size) {
if (counts.containsKey(size))
return counts.get(size);
else
return 0;
}
}
1 class header
3 fields
2 Map or List for counts
1 state count (int) or reasonable attempt to add them up in totalStates
-1 if either is nonprivate
4 constructor
1 header and super(data)
1 initialize counts
2 correctly records initial state
1 attempt (e.g., handles just one of 2 fields)
1 correct
2 totalStates (two possibilities)
2 using a state count field
1 attempt to increment in add/remove method (at least 2 of them)
1 all correct (increments in all 3, returns field)
2 adding up all of the counts
1 reasonable attempt to add them up
1 all correct
3 overriding two add methods and remove
1 at least two of them are overridden
1 at least two of them call the super version
1 all three overridden and call super version
4 correctly handles modifications
1 reasonable attempt in at least one method
1 in at least one method it correctly increments size if seen previously
1 in at least one method it correctly handles a new size (count of 1)
1 same modification code appears in all 3 methods (or 3 calls to private)
3 sizeCount
1 reasonable attempt (method declared, attempt to access their map or list)
1 correct if this is a size we've seen (in map or list)
1 correct (returns 0) if this is a size we haven't seen
Array based solutions go to the question leader.
If they destroy a method they inherited (e.g., size, indexOf): -1, -2, -3 based
on quality (max -3).
Alternate solution to #4 using List
public class AnalyzingDocumentList extends DocumentList {
private List count;
private int stateCount;
public AnalyzingDocumentList(int capacity) {
super(capacity);
count = new ArrayList();
count.add(1);
stateCount = 1;
}
public void add(Document d) {
super.add(d);
stateUpdate();
}
public void add(int index, Document d) {
super.add(index, d);
stateUpdate();
}
public void remove(int index) {
super.remove(index);
stateUpdate();
}
private void stateUpdate() {
stateCount++;
int size = size();
if (size >= count.size())
count.add(1);
else
count.set(size, count.get(size) + 1);
}
public int totalStates() {
return stateCount;
}
public int sizeCount(int size) {
if (size >= 0 && size < count.size())
return count.get(size);
else
return 0;
}
}
Alternate solution to #4 using int[]
public class AnalyzingDocumentList extends DocumentList {
private int[] count;
private int stateCount;
public AnalyzingDocumentList(int capacity) {
super(capacity);
count = new int[capacity + 1];
count[0]++;
stateCount = 1;
}
public void add(Document d) {
super.add(d);
stateUpdate();
}
public void add(int index, Document d) {
super.add(index, d);
stateUpdate();
}
public void remove(int index) {
super.remove(index);
stateUpdate();
}
private void stateUpdate() {
stateCount++;
count[size()]++;
}
public int totalStates() {
return stateCount;
}
public int sizeCount(int size) {
if (size >= 0 && size < count.length)
return count[size];
else
return 0;
}
}
Problem #5
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() {
if (getCalories() == 0)
return 0.0;
else
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
4 fields (1 point each, -1 if not private, okay to have extra field(s) for
calories or fat calories or percent fat)
3 constructor
1 correct header
1 exception
1 sets four fields correctly
1 getName correct
2 getCalories correct
1 attempt
1 correct
3 percentFat correct (don't have to worry about getCalories() == 0)
1 attempt
2 correct (-1 if close--e.g., missing the *100)
2 toString correct
1 includes all four fields
1 correct format
4 compareTo
1 attempt to test difference in percent fat
1 returns negative when this.percentFat < other.percentFat
1 returns positive when this.percentFat > other.percentFat
1 returns name comparison when percentFat equal
Problem #6
Solution:
public void mirror() {
mirror(overallRoot);
}
private void mirror(IntTreeNode root) {
if (root != null) {
IntTreeNode temp = root.left;
root.left = root.right;
root.right = temp;
mirror(root.left);
mirror(root.right);
}
}
1 public header
1 private header with a root parameter (IntTreeNode return is okay if they
actually return root at the end)
1 public method calls private method passing it overallRoot
4 null test
2 attempt (tested this case)
2 correct (tree not changed in this case)
3 recusively mirrors left subtree (don't worry about switching bugs for this)
1 attempt (if you see a call on mirror(root.left), they get this point)
2 correct (always called for non-null root--ok if they prevent a call when
root.left is null)
3 recursively mirrors right subtree (don't worry about switching bugs for this)
1 attempt (if you see a call on mirror(root.right), they get this point)
2 correct (always called for non-null root--ok if they prevent a call when
root.right is null)
7 switches root.left and root.right
1 minimal attempt (e.g., switches root.left.data and root.right.data)
6 all correct (always switches correctly for non-null root); -4 for no use
of temp, -2 for other errors
-10 if they solve it by constructing the mirror image
Problem #7
Solution:
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;
}
}
}
1 header (can be either reverse3 or rotate3)
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)
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
2 Managing to redirect sequence of three next fields somewhere in their code:
before:
+------+------+ +------+------+ +------+------+
| n1 | +--+---> | n2 | +--+---> | n3 | +--+--> other
+------+------+ +------+------+ +------+------+
after:
+------+------+ +------+------+ +------+------+
| n3 | +--+---> | n2 | +--+---> | n1 | +--+--> other
+------+------+ +------+------+ +------+------+
12 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)
2 3-element list
2 4-element list
2 6-element list (1 pt if just first triple is bad)
2 7-element list (1 pt if just first triple is bad)
2 9-element list (1 pt if just first triple is bad)
2 11-element list (1 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 5 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.
Alternate solution to #7 using recursion
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;
}
Stuart Reges
Last modified: Fri Sep 16 16:16:07 PDT 2011