*********** Answers to Test 1, Fall 2009, Compsci 100 Problem 1 * *********** Part A: calc(31) = 31 calc(32) = 63 calc(33) = 63 Part B: Smallest value x such that calc(x) returns 2047 is 1024. From seeing the pattern or analyzing the code, calc returns the sum of powers of 2 less than or equal to n. To get 2047 we need to add all powers of two from 1, 2, 4,..., 1024. Anything less won't get 2047. So, calc(1024) = 2047 and calc(1023) = 1023. Part C: calc(2^n) is 1 + 2 + 4 + 8 + ... + 2^n, sum of powers of 2 which is one less than the next power of 2 or 2^(n+1) - 1 Part D: O(log n) because the loop iterates as many times as val can be multiplied by 2 before exceeding n. This is precisely log_2(n), we ignore the base in big-Oh Part E: calc(calc(256)) = calc(511) = 511. All these values are given in the beginning of the problem where the output for calc(256) and calc(511) is shown. calc(calc(2^n)) is 2^(n+1) - 1, the same as the answer for C. This is because calc of one less than a power of 2 is the same as calc of the previous power of 2, e.g., calc(511) = 511 and calc(1023) = 1023. Part F: public String bigKey(Map map){ int max = Integer.MIN_Value; String ms = null; for(String s : map.keySet()){ int val = map.get(s); if (val > max){ max = val; ms = s; } } return ms; } *********** Problem 2 * *********** Part A: a 6-tower is a 4-tower + (5x4) + (6x5) = 9+5+6 = 20 Part B: a 100-tower is 100*(101)/2 - 1, i.e., the sum of the numbers from 2-100 which is (sum:1-100) - 1 Part C: a 6-tower is a 4-tower + (5x4) + (6x5) = 20+20+30=70 Part D: B(n) = B(n-1) + (n X (n-1)) because an n-tower is an (n-1)-tower on top of an n X (n-1) rectangle Part E: public int blocks(int n) { if (n == 2) return 2; return blocks(n-1) + n*(n-1); } Part F: The bottom rectangle is n X (n-1) which is n^2. There are roughly n such rectangles which yields O(n^3). It's not the case that each of the n-rectangles is n^2, but clearly at least half of them are O(n^2), i.e., the middle one is n/2 X (n/2-1) which is still O(n^2), so there are n/2 n^2 rectangles More formally we can find the solution to the recurrence (this isn't what you were expected to do) b(n) = b(n-1) + n X (n-1) --- from the general recurrence we have b(n-1) = b(n-2) + (n-1) X (n-2) just substituting n-1 for n. expanding we get b(n) = [b(n-2) + (n^2 -3n + 2)] + n^2 - n = b(n-2) + 2n^2 - 4n + 2 expanding for b(n-2) = b(n-3) + (n-2) X (n-3) b(n) = [b(n-3) + n^2 - 5n + 6] + 2n^2 -4n + 2 = b(n-3) + 3n^2 - 9n + 8 we can now see a pattern: b(n) = b(n-k) + kn^2 - .... we don't care about the ... because it's less than n^2 in big-Oh this expression is true for n=1,2,3 above, so "true" for k [proof of induction needed formally] Since this is true for all values of k, let k=n! b(n) = b(n-n) + n*n^2 = b(0) + n^3 but b(0) requires O(1) time, so b(n) = n^3 *********** Problem 3 * *********** Part A: Use a snake-path: 0 1 2 3 7 6 5 4 8 9 a b f e d c Part B: The longest path is a snake-path with 0-9 followed by a-z, this is a total of 36 values for a length 36 path Part C: All values the same or a checkerboard like this expanded to nXn 0 1 0 1 0 .. 1 0 1 0 1 .. 0 1 0 1 0 .. 1 0 1 0 1 .. .. Part D: return 1 + Math.max(Math.max(left,right), Math.max(up,down)); We need the +1 to account for the current square. Note that otherwise all values returned would be zero from base cases. *********** Problem 4 * *********** Part A: The call to split(":") separates the name from the class list, the call to split(",") separates all the classes so they can be looped over. The call to .indexOf works like .contains, e.g., it determines if the parameter course is contained in the array Part B: do something that looks reasonable, then implement it in part C Part C: Here's a method that uses an inner Comparable class: ---- private class CourseComp implements Comparable{ String myName; int myEnroll; public CourseComp(String s, int enroll){ myName = s; myEnroll = enroll; } public int compareTo(CourseComp o) { int diff = o.myEnroll - myEnroll; if (diff != 0) return diff; return myName.compareTo(o.myName); } } public String[] enrollSort(String[] list){ HashMap map = new HashMap(); for(String s : list){ String[] first = s.split(":"); String[] courses = first[1].split(","); for(String cs : courses){ if (! map.containsKey(cs)){ map.put(cs, 0); } map.put(cs, map.get(cs)+1); } } String[] ret = new String[map.keySet().size()]; ArrayList temp = new ArrayList(); for(String cs : map.keySet()){ temp.add(new CourseComp(cs,map.get(cs))); } Collections.sort(temp); for(int k=0; k < ret.length; k++){ ret[k] = temp.get(k).myName; } return ret; } *********** Problem 5 * *********** Part A: public int idleTime(Interval[] list){ int sum = 0; for(int k=0; k < list.length-1; k++){ sum += list[k].timeUntil(list[k+1]); } return sum; } Part B: public Interval[] mostBusy(Interval[] list){ ArrayList best = new ArrayList(); Arrays.sort(list); best.add(list[0]); Interval last = list[0]; for(int k=1; k < list.length; k++){ Interval current = list[k]; if (!current.overLaps(last)){ best.add(current); last = current; } } return best.toArray(new Interval[0]); } Part C: public int compareTo(Interval o) { int diff = myEnd - o.myEnd; if (diff != 0) return diff; return o.myStart - myStart; }