001package algs11; 002 003import java.util.Arrays; 004import stdlib.*; 005 006/** 007 * This is a skeleton file for your homework. Edit the sections marked TODO. You 008 * may add new functions. You may also edit the function "main" to test your 009 * code. 010 * 011 * You must not add static variables. You MAY add static functions, just not 012 * static variables. 013 * 014 * It is okay to add functions, such as 015 * 016 * <pre> 017 * public static double sumHelper (double[] list, int i, double sumSoFar) { 018 * </pre> 019 * 020 * but it is NOT okay to add static variables, such as 021 * 022 * <pre> 023 * public static int x; 024 * </pre> 025 * 026 * As for homework 1, you must not change the declaration of any method. 027 * 028 * You can edit the main function all you want. I will not run your main 029 * function when grading. 030 */ 031public class MySecondHomework { 032 033 /** 034 * As a model, here is a minValue function, both iteratively and recursively 035 */ 036 /** iterative version */ 037 public static double minValueI (double[] list) { 038 double result = list[0]; 039 int i = 1; 040 while (i < list.length) { 041 if (list[i] < result) result = list[i]; 042 i = i + 1; 043 } 044 return result; 045 } 046 047 /** recursive version */ 048 public static double minValue (double[] list) { 049 return minValueHelper (list, 1, list[0]); 050 } 051 private static double minValueHelper (double[] list, int i, double result) { 052 if (i < list.length) { 053 if (list[i] < result) result = list[i]; 054 result = minValueHelper (list, i + 1, result); 055 } 056 return result; 057 } 058 059 /** 060 * PROBLEM 1: Translate the following sum function from iterative to 061 * recursive. 062 * 063 * You should write a helper method. You may not use any "fields" to solve 064 * this problem (a field is a variable that is declared "outside" of the 065 * function declaration --- either before or after). 066 */ 067 public static double sumI (double[] a) { 068 double result = 0.0; 069 int i = 0; 070 while (i < a.length) { 071 result = result + a[i]; 072 i = i + 1; 073 } 074 return result; 075 } 076 public static double sum (double[] a) { 077 // TODO 078 return StdRandom.uniform (); 079 } 080 081 /** 082 * PROBLEM 2: Do the same translation for this in-place reverse function 083 * 084 * You should write a helper method. You may not use any "fields" to solve 085 * this problem (a field is a variable that is declared "outside" of the 086 * function declaration --- either before or after). 087 */ 088 public static void reverseI (double[] a) { 089 int hi = a.length - 1; 090 int lo = 0; 091 while (lo < hi) { 092 double loVal = a[lo]; 093 double hiVal = a[hi]; 094 a[hi] = loVal; 095 a[lo] = hiVal; 096 lo = lo + 1; 097 hi = hi - 1; 098 } 099 } 100 public static void reverse (double[] a) { 101 // TODO 102 } 103 104 /** 105 * PROBLEM 3: The following function draws mickey mouse, if you call it like 106 * this from main: 107 * 108 * <pre> 109 * draw (.5, .5, .25); 110 * </pre> 111 * 112 * Change the code to draw mickey moose instead. Your solution should be 113 * recursive. 114 * 115 * Before picture: 116 * http://fpl.cs.depaul.edu/jriely/ds1/images/MickeyMouse.png After picture: 117 * http://fpl.cs.depaul.edu/jriely/ds1/images/MickeyMoose.png 118 * 119 * You may not use any "fields" to solve this problem (a field is a variable 120 * that is declared "outside" of the function declaration --- either before 121 * or after). 122 */ 123 public static void draw (double centerX, double centerY, double radius) { 124 // TODO 125 if (radius < .0005) return; 126 127 StdDraw.setPenColor (StdDraw.LIGHT_GRAY); 128 StdDraw.filledCircle (centerX, centerY, radius); 129 StdDraw.setPenColor (StdDraw.BLACK); 130 StdDraw.circle (centerX, centerY, radius); 131 132 double change = radius * 0.90; 133 134 StdDraw.setPenColor (StdDraw.LIGHT_GRAY); 135 StdDraw.filledCircle (centerX + change, centerY + change, radius / 2); 136 StdDraw.setPenColor (StdDraw.BLACK); 137 StdDraw.circle (centerX + change, centerY + change, radius / 2); 138 139 StdDraw.setPenColor (StdDraw.LIGHT_GRAY); 140 StdDraw.filledCircle (centerX - change, centerY + change, radius / 2); 141 StdDraw.setPenColor (StdDraw.BLACK); 142 StdDraw.circle (centerX - change, centerY + change, radius / 2); 143 } 144 145 /** 146 * PROBLEM 4: Run runTerribleLoop for one hour. You can stop the program 147 * using the red "stop" square in eclipse. Fill in the OUTPUT line below 148 * with the numbers you saw LAST --- edit the line, replacing the two ... 149 * with what you saw: 150 * 151 * OUTPUT: terribleFibonacci(...)=... // TODO 152 * 153 * Comment: the code uses "long" variables, which are like "int", but 154 * bigger. It's because fibonacci numbers get really big really fast. 155 */ 156 public static void runTerribleLoop () { 157 for (int N = 0; N < 100; N++) 158 StdOut.format ("terribleFibonacci(%2d)=%d\n", N, terribleFibonacci (N)); 159 } 160 public static long terribleFibonacci (int n) { 161 if (n <= 1) return n; 162 return terribleFibonacci (n - 1) + terribleFibonacci (n - 2); 163 } 164 165 /** 166 * PROBLEM 5: The implementation of terribleFibonacci is TERRIBLE! Write a 167 * more efficient version of fibonacci. Do not change runFibonacciLoop or 168 * runFibonacciSomeValues. 169 * 170 * To make fibonacci run faster, you want it so that each call to 171 * fibonacci(n) computes the fibonacci numbers between 0 and n once, not 172 * over and over again. 173 * 174 * Comment: You will want to use a local variable of type "long" rather than 175 * type "int", for the reasons discussed above. 176 * 177 * Comment: At some point, your fibonacci numbers might become negative. 178 * This is normal and expected. 179 * http://en.wikipedia.org/wiki/Integer_overflow We discuss this at length 180 * in our systems classes. 181 * 182 * You may not use any "fields" to solve this problem (a field is a variable 183 * that is declared "outside" of the function declaration --- either before 184 * or after). 185 * 186 * You may use a loop on this problem. 187 * You do not need to use recursion. 188 */ 189 public static void runFibonacciLoop () { 190 for (int N = 0; N < 100; N++) 191 StdOut.format ("fibonacci(%2d)=%d\n", N, fibonacci (N)); 192 } 193 public static long fibonacci (int n) { 194 return 0; // TODO 195 } 196 197 /* 198 * A main function for debugging -- change the name to "main" to run it (and 199 * rename the existing main method to something else). Change the test as 200 * appropriate. 201 */ 202 public static void main1 (String[] args) { 203 Trace.drawStepsOfMethod ("minValueI"); 204 Trace.drawStepsOfMethod ("minValue"); 205 Trace.drawStepsOfMethod ("minValueHelper"); 206 Trace.run (); 207 testMinValue ("11 21 9 31 41"); 208 } 209 210 /** 211 * A test program, using private helper functions. See below. 212 * To make typing tests a little easier, I've written a function to convert strings to arrays. See below. 213 * You can modify this -- it is not graded. 214 */ 215 public static void main (String[] args) { 216 testSum ("11 21 81 -41 51 61"); 217 testSum ("11 21 81 -41 51"); 218 testSum ("11 21 81 -41"); 219 testSum ("11 21 81"); 220 testSum ("11 21"); 221 testSum ("11"); 222 testSum (""); 223 224 testReverse ("11 21 81 -41 51 61"); 225 testReverse ("11 21 81 -41 51"); 226 testReverse ("11 21 81 -41"); 227 testReverse ("11 21 81"); 228 testReverse ("11 21"); 229 testReverse ("11"); 230 testReverse (""); 231 232 testFibonacci (0, 0); 233 testFibonacci (1, 1); 234 testFibonacci (1, 2); 235 testFibonacci (2, 3); 236 testFibonacci (21, 8); 237 testFibonacci (233, 13); 238 testFibonacci (75025, 25); 239 testFibonacci ( 1_836_311_903L, 46); 240 testFibonacci ( 2_971_215_073L, 47); 241 testFibonacci ( 308_061_521_170_129L, 71); 242 testFibonacci ( 498_454_011_879_264L, 72); 243 testFibonacci ( 7_540_113_804_746_346_429L, 92); 244 // 9_223_372_036_854_775_807L == Long.MAX_VALUE 245 testFibonacci (-6_246_583_658_587_674_878L, 93); 246 testFibonacci ( -813_251_414_217_914_645L, 376); 247 StdOut.println ("Finished tests"); 248 249 draw (.5, .5, .25); 250 251 // TODO: uncomment these temporarily when you want to see the output of your Fibonacci functions 252 //runTerribleLoop (); 253 //runFibonacciLoop(); 254 } 255 256 /* Test functions --- lot's of similar code! */ 257 private static void testSum (String list) { 258 double[] aList = doublesFromString (list); 259 double expected = sumI (aList); 260 double actual = sum (aList); 261 if (! Arrays.equals (aList, doublesFromString (list))) { 262 StdOut.format ("Failed sum([%s]): Array modified\n", list); 263 } 264 if (expected != actual) { 265 StdOut.format ("Failed sum([%s]): Expecting (%.1f) Actual (%.1f)\n", list, expected, actual); 266 } 267 } 268 private static void testMinValue (String list) { 269 double[] aList = doublesFromString (list); 270 double expected = minValueI (aList); 271 double actual = minValue (aList); 272 if (! Arrays.equals (aList, doublesFromString (list))) { 273 StdOut.format ("Failed minValue([%s]): Array modified\n", list); 274 } 275 if (expected != actual) { 276 StdOut.format ("Failed minValue([%s]): Expecting (%.1f) Actual (%.1f)\n", list, expected, actual); 277 } 278 } 279 private static void testReverse (String list) { 280 double[] expected = doublesFromString (list); 281 reverseI (expected); 282 double[] actual = doublesFromString (list); 283 reverse (actual); 284 // != does not do what we want on arrays 285 if (! Arrays.equals (expected, actual)) { 286 StdOut.format ("Failed reverse([%s]): Expecting (%s) Actual (%s)\n", list, Arrays.toString (expected), Arrays.toString (actual)); 287 } 288 } 289 private static void testFibonacci (long expected, int n) { 290 long actual = fibonacci (n); 291 if (expected != actual) { 292 StdOut.format ("Failed fibonacci(%d): Expecting (%d) Actual (%d)\n", n, expected, actual); 293 } 294 } 295 296 /* A utility function to create an array of doubles from a string. */ 297 // The string should include a list of numbers, separated by single spaces. 298 private static double[] doublesFromString (String s) { 299 if ("".equals (s)) return new double [0]; // empty array is a special case 300 String[] nums = s.split (" "); 301 double[] result = new double[nums.length]; 302 for (int i = nums.length-1; i >= 0; i--) { 303 try { 304 result[i] = Double.parseDouble (nums[i]); 305 } catch (NumberFormatException e) { 306 throw new IllegalArgumentException (String.format ("Bad argument \"%s\": could not parse \"%s\" as a double", s, nums[i])); 307 } 308 } 309 return result; 310 } 311}