CS307 Midterm 1 Solution and Grading Criteria. Grading acronyms OBOE - Off by one error. Calculation is off by one. AIOBE - Array Index out of Bounds Exception will occur NPE - Null Pointer Exception will occurs ABA - Answer by Accident GCE - Gross Conceptual Error. Did not answer the question asked or showed fundamental misunderstanding NAP - No answer provided. No answer given on test ECF - Error carried forward. 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.) 1. Answer as shown or -2 unless question allows partial credit. No points off for differences in spacing and capitalization. A. 21 B. 13 C. 160 D. 4 6 11 10 13 E. 6 5 3 F. 12 3 G. acxyz H. Yes it can. s could be null despite the commented precondition or the length of s could be 0. (Either reason gets full credit.) I. Syntax error or compile error. (-2 for just error or runtime error) J. false K. true L. 30 M. No. Standard ticket inherits a toString method from the Object class. (Or words to that effect.) N. No. Since the class implements the Comparable interface, but does not implement the method compareTo, it will not compile. (Or words to that effect.) O. 0 2. A simple question on array processing and working with Strings. The most common problems were thinking list was a single String instead of an array of Strings. Also a lot of students did not know how to call the static method isLetter from the Character class. Students could assume non of the elements of list were null. Some very good solutions choose to decompose finding the similarity score into another method. These attempts were almost always correct. I saw a lot of gacky uses of continue. If the logic on the if test on lengths is changed from != to == there is no need to use continue. Suggested solution: public static int getMaxSimilarityScore(String[] list, String source){ assert list != null && list.length > 0 && source != null && source.length() > 0; int max = 0; int current; for(int i = 0; i < list.length; i++){ current = 0; if(source.length() == list[i].length()){ for(int j = 0; j < source.length(); j++){ if( source.charAt(j) == list[i].charAt(j)){ if( source.charAt(j) == 'k' || source.charAt(j) == 'q') current += 3; else if( Character.isLetter(source.charAt(j))) current += 2; else current++; } } } max = Math.max(current, max); System.out.println(current); } return max; } Criteria: loop through list attempt: 2 correct: 3 check same length: 2 loop through all chars in Strings of equal length attempt: 2 correct: 2 update / calculate similarity score attempt: 2 correct: 5 track or find maximum score attempt: 2 correct: 3 return 1 points off for various errors also possible 3. A very interesting question. The algorithm may not have been obvious and required some thought before writing code. There were also a number of different approaches. Some students choose to try and find the leftmost, rightmost, uppermost, and lowermost occurrences of the target character. After finding those the width and height can be easily calculated. Some students tried to find the coordinates of the upper left corner of the box and then update the width and height whenever new instances of the target character were found. I saw working versions of both algorithms. The case also had to be handles if the target was not present and some students did not consider this possibility even though it was explicitly stated in the question. Some common problems: The top left corner of the bounding box may not actually contain the target character. The first example was a case such as this, but some students still thought the row and column (or y and x coordinate) would be based on the first character found. This was true of for the row depending on the search strategy used, but not the column. Another common problem was trying to calculate width and height based on the number of rows or columns that contain the target. A lot of off by one errors (OBOE) when calculating width and height. if top row of the box is 0 and bottom row of the box is 3, the height is 4 (3 - 0 + 1) not 3 (3 - 0). Using break to try and get out of nested loop. A break only breaks out of the loop it is in. Something else would need to be done to get out of the outer loop. (Like use a boolean. Then no break is needed.) Suggested solution: public static Rectangle getMinBoundBox(char[][] table, char tgt){ int minRow = table.length; int maxRow = -1; int minCol = table[0].length; int maxCol = -1; for(int r = 0; r < table.length; r++) for(int c = 0; c < table[0].length; c++) if(table[r][c] == tgt){ if(r < minRow) minRow= r; if(r > maxRow) maxRow = r; if(c < minCol) minCol = c; if(c > maxCol) maxCol = c; } Rectangle result; if( maxRow == -1 ) result = new Rectangle(0,0,0,0); else result = new Rectangle(minCol, minRow, maxCol - minCol + 1, maxRow - minRow + 1); return result; } This is a very simple minded solution. For instance after the first occurrence of target the first if check (r < minRow) will never be true again, but I keep checking anyway. Note, this doesn't change the Big O. There were some very interesting solutions that had 4 sets of nested loops. Each set found one corner of the box. Given a large bounding box this was a very efficient solution even though it is a lot of code. search for occurrences of target attempt: 3 correct: 4 vars for corners or top left and width, height: 2 determine appropriate bounds: attempt: 3 correct: 11 Create resulting Rectangle: attempt 2 correct 4 return 1 4. A simple question to evaluate the ability to create a class. public class TicketRecord{ private int numGiven; private double totalValue; private int numContested; public TicketRecord(){} // all initialized to 0 automatically //value >= 0 public void recordTicket(double value){ assert value >= 0 : "failed precondition."; numGiven++; totalValue += value; } public void contestTicket(){ numContested++; } // pre: at least one ticket has been given public double averageValue(){ assert numGiven > 0 : "failed precondition."; return totalValue / numGiven; } } Points: class header attempt: 1 point correct: 1 point instance variables: 2 points (-1 if not private) ticket given method attempt: 2 point correct: 2 points. (must use parameter, not user input) ticket contested method attempt: 1 point correct: 2 points ticket given method attempt: 2 point correct: 2 points. must correctly perform floating point division or -1