CS307 Spring 2010 Midterm 1 Solution and Grading Criteria.
Grading acronyms:
AIOBE - Array Index out of Bounds Exception may occur
BOD - Benefit of the Doubt. Not certain code works, but, can't prove otherwise
Gacky or Gack - Code very hard to understand even though it works or solution
is not elegant. (Generally no points off for this.)
GCE - Gross Conceptual Error. Did not answer the question asked or showed
fundamental misunderstanding
LE - Logic error in code.
NAP - No answer provided. No answer given on test
NN - Not necessary. Code is unneeded. Generally no points off
NPE - Null Pointer Exception may occur
OBOE - Off by one error. Calculation is off by one.
1.A You should comment all your code and programs, even the ones you only intend for your own use. The reason to do this is 6 months after you write a program you will forget how it works or what you were trying to do and it is more time consuming to change or update. (Because you have to figure out what the heck you code dies.)
OR words to that affect. Partial credit possible
B. Making a project open source is selfish because programmers will work on it and you don't have to pay them. You can incorporate their good changes into the project for free. Allen also related that when they went open source a lot more bugs in the code were found and reported so they could be fixed. OR word to that affect. Partial credit possible
C. 12
D. laeyyy
E. 39
F. O(N)
G. O(N^2)
H. O(N^2)
I. O(NlogN) // base 2 okay
J. O(N^2)
K. O(N^2)
L. 63 seconds
M. 840 / 19 seconds OR 10 * 4 * 21 / 19 seconds OR 40 * 21 / 19 seconds OR a little more than 44 seconds. (40 seconds is not correct.)
N. 12,500 pieces of data or 50,000 / 4
O. Sort the data.
Without sorting the work is 50,000 * 1,000,000 / 2 (assume on average we look at half the elements. = 25,000,000,000 operations.
Sorting will take 1,000,000 log 1,000,000 = 1,000,000 * 20 = 20,000,000 ops plus the binary searches = 50,000 * 20 = 1,000,000 = 21,000,000 ops total. 21,000,000 << 25,000,000,
1 point for the math, 1 point for correct math.)
2. Comments. This was not an easy question. There was a lot to keep track of. Common mistakes were not resizing the underlying array if necessary, not update the size instance variable, treating the native array like an ArrayList, and using mehtods that were not allowed. Generally students did well on this question.
Suggested Solution:
public void insertAfter(E newValue, E tgt){
assert newValue != null && tgt != null
&& !newValue.equals(tgt);
int numPresent = 0;
for(int i = 0; i < size; i++)
if(elements[i].equals(tgt))
numPresent++;
// use temp array.
Object[] temp = new Object[numPresent + elements.length];
int indexNew = 0;
for(int i = 0; i < size; i++){
temp[indexNew] = elements[i];
indexNew++;
if(elements[i].equals(tgt)){
temp[indexNew] = newValue;
indexNew++;
}
}
elements = temp;
size += numPresent;
}
Criteria:
find elements equal to tgt: attempt 2 points, correct: 2 points
insert new values after each occurrence:
attempt: 3 points, correct: 7 points
resize array if necesaryL attempt: 2 points, correct: 2 points
update size correctly: 2 points:
non allowed methods of classes: -7 points
3. Comments: This was meant to be an easy question. All you had to do was move through the linked list as we showed in class. It was not necessary to alter the list in any way. I think one thf most common problems was the termintation condition for the while loop. A lot of answers went like this:
Node temp = first;
while(temp.getNext() != null)
That causes two problems. First if the list is empty you get a null pointer exception the first time you dereference tail. if the list is not empty that causes you to skip the last node. The correct test is tail != null. You actually want tail to walk off the list.
Students generally did well on ths question.
Suggested Solution
public int numNull() {
Node temp = first;
int count = 0;
while(temp != null){
if(temp.getData() == null)
count++;
temp = temp.getNext();
}
return count;
}
Criteria:
Start temp node at first: 1 point
traverse list: attempt 1 point
correct: 6 points. -6 if no movement, -3 if Null Pointer Exception
check if data in node null: attempt 1 point, correct 3 points
keep count of data elements equal to null: 2 points
return result: 1 point
- 7 if not O(1) space or use un allowed methods / classes
4. Comments: This was essnetially a question about being able to use an iterator. Because you had to remove you had to explicity use th iterator. A for each loop would not work here. Students generally did well on this question.
Suggested Solution:
public static UnsortedSet removeBigRectangles
(UnsortedSet set, double a) {
UnsortedSet result = new UnsortedSet();
Iterator it = set.iterator();
while(it.hasNext()){
Rectangle temp = it.next();
if(temp.getArea() >= a){
it.remove();
result.add(temp);
}
}
return result;
}
Criteria:
Create result: 1 point
obtain iterator: 2 points
use iterator to look at all elements in set:
attempt 2 points, correct 4 points
check if are of current Rectangle >= target area (> or >= okay):
1 point
if criteria met, remove via iterator: 2 points
add to result: 2 points
return result: 1 point
- 6 if unallowed classes or methods
5. comments. this one turned out to be a real bear. I guess it was different enough from other recursive backtracking problems we had seen. I thin it would have been easier if the helper had also included an int that was the current index pf the item from originalCon to consider. One student went ahead and added this method and that made for a very simple solution. My intention was for you to remove items from originalCon and then put them back. Instead MOST people try to use for loops. In some cases this worked, in a lot it didn't. I actually typed ina bout 40 - 50 of the solutions to verify they worked or they didn't. With so many unexpected for loops it made it really hard to grade the question per the critera. The grading was pretty tough, bu that gets made up for by the curve. Additionally, I think the for loop solutions with recursion that did work took advanatge of the fact that the UnsortedSet add method woudl handle adding a dupicate. (by not adding it.) That was fine.
Common problems were trying to add subset to result, (It is an ArrayList not an UnsortedSet.) Not having the right parameter types in the recurisive calls, not reaching the base case, (a lot of stack over flow errors on the solutions I typed in), not making recursive calls with the item in the subsete and not in the subset. Not removing items from the subset once they were added or removing them from a different spot.
Suggested Solution
private void helper(
UnsortedSet> result,
ArrayList subset, ArrayList originalCon) {
if(originalCon.size() == 0){
UnsortedSet temp = new UnsortedSet();
for(int i = 0; i < subset.size(); i++)
temp.add(subset.get(i));
result.add(temp);
}
else{
E temp = originalCon.remove(myCon.size() - 1);
// subset without temp
helper(result, subset);
// subset with temp
subset.add(temp);
helper(result, subset);
// take it out of subset and add back to con
subset.remove(subset.size() - 1);
originalCon.add(temp);
}
}
Criteria:
Base Case:
check if reached; attempt: 1 point, correct: 4 points
create new set: 1 point
copy values from subset array to new set: attempt 1 point, correct 1
add new set to result: 1 point
Recursive Case:
remove item from original Con (consider 1 item): 1 point
call helper without adding current item to subset: 3 points
add to subset: 1 point
call helper with current item in subset: 3 points
remove from subset: 1 point
add back to con: 2 points
One for loop solution that work:
private void helper(
UnsortedSet> result,
ArrayList subset, ArrayList originalCon) {
UnsortedSet temp = new UnsortedSet();
for(E i : subset)
temp.add(i);
result.add(temp);
int limit = originalCon.size();
for(int i = 0; i < limit; i++){
subset.add(originalCon.remove(0)); // ineffiecient remove, ok
helper(result, subset, originalCon);
originalCon.add(subset.remove( subset.size() - 1));
}
}