Solutions to the Final Exam Practice Problems Prepared by Prof. Ron Williams (rjw@ccs.neu.edu) I have not tried to run all the code I've included here, so you may encounter some errors. If you do, feel free to let me know. -- RJW ////////////// // Problem 1. ////////////// //(a) ///// XYYYY1 XXYYY2 XXXYY3 XXXXY4 XXXXX5 ///// //(b) ///// Array check for array a true Array check for array b 3: 44, 35 false Array check for array c 0: 23, 22 false ////////////// // Problem 2. ////////////// public class EvenNumbers { public static void main (String[] args) { for (int i = 1; i <= 50; i++) { System.out.println(2*i); } } } /////////////// // Problem 3. ////////////// //(a) ///// void statistics(){ int num, sum = 0; for (int i = 1; i <= 10; i++){ num = -100 + (int) (201 * Math.random()); console.out.println(num); sum += num; } console.out.println("The sum is " + sum); console.out.println("The average is " + sum/10.0); } ///// //(b) ///// boolean isRomanUpperCase(char c){ return c >= 'A' && c <= 'Z'; } ///// //(c) ///// String replaceUpperCase(String s){ char c; // start with an empty StringBuffer of the right length StringBuffer sb = new StringBuffer(s.length()); // copy the characters one by one, but in place of uppercase // letters use '*' for (int i = 0; i < s.length(); i++){ c = s.charAt(i); if (isRomanUpperCase(c) sb.append('*'); else sb.append(c); } // convert StringBuffer to String and return it return new String(sb); } // Another approach would be to convert the String to a StringBuffer sb // immediately (using a StringBuffer constructor), then use sb.charAt(i) // and sb.setCharAt(i) in the loop. The approach given above generalizes // more readily to the related problem of creating a function that simply // removes all upper case characters from the string. ///// //(d) ///// int findMaxLoc(int a[], int low, int high){ int maxIndex = low; for (int i = low; i < high; i++){ if (a[i] > a[maxIndex]) maxIndex = i; } return maxIndex; } ///// //(e) ///// int[] randArray = new int[10]; for (int i = 0; i < 10; i++){ randArray[i] = -100 + (int) (201 * Math.random()); } int maxIndex = findMaxLoc(randArray, 4, 9); int maxVal = randArray[maxIndex]; console.out.println("The largest value among those elements is " + maxVal); ///// //(f) ///// for (int i = 1; i <= n; i++){ for (int j = 1; j <= i; j++) console.out.print("*"); console.out.println(); } ///// //(g) ///// // This solution uses simple string concatenation, but Java probably // actually implements this using StringBuffers implicitly String indent(int n){ String s = ""; for (i = 1; i <= n; i++) s = s + " "; // could write this even more concisely as s += " "; return s; } // Here's a solution using StringBuffers explicitly // String indent(int n){ // // create an empty StringBuffer that can hold n characters // StringBuffer sb = new StringBuffer(n); // for (i = 1; i <= n; i++) // sb.append(" "); // return new String(sb); // } /////////////// // Problem 4. ////////////// public synchronized void steps(){ Graphics2D g = window.getBufferGraphics(); g.setPaint(Color.black); // get number of steps from user - should do some sanity checking, // but this is good enough for now int nSteps = console.in.demandInt("Number of steps:"); Rectangle2D.Double r = new Rectangle2D.Double(); double stepWidth = (double)window.getWidth()/nSteps; double stepRise = (double)window.getHeight()/nSteps; // upper left corner of first step double x = 0.0; double y = window.getHeight() - stepRise; // height of first step double stepHeight = stepRise; for (int i = 1; i <= nSteps; i++){ // paint the step r.setRect(x, y, stepWidth, stepHeight); g.fill(r); // upper left corner and height of next step x += stepWidth; y -= stepRise; stepHeight += stepRise; } window.repaint(); } ////////////// // Problem 5. ////////////// // (a) /////// public boolean isHigherThan(Cube otherCube){ return (y - size/2 < otherCube.getY() - otherCube.getSize()/2); } /////// // (b) /////// // Need to first make sure the size is no larger than the smaller of // the window width and the window height, so we add two lines at // the beginning to do this: public void adjustToFit(window){ int maxSize = Math.min(window.getWidth(), window.getHeight()); if (size > maxSize) size = maxSize; adjustX(window); // same as before adjustY(window); // same as before } ////////////// // Problem 6. ////////////// // (a) /////// // create the Cube objects Cube c1 = new Cube(200.0, 200.0, 80.0, Color.red); Cube c2 = new Cube(100.0, 300.0, 50.0, Color.blue); // draw them in the graphics window Graphics2D g = window.getBufferGraphics(); c1.draw(g); c2.draw(g); window.repaint(); /////// // (b) /////// // create the Cube objects Cube c1 = new Cube(200*Math.random(), 200*Math.random(), 200*Math.random(), Color.red); Cube c2 = new Cube(200*Math.random, 200*Math.random, 200*Math.random, Color.green); // test to see which is higher and report the result if (c1.isHigherThan(c2)) console.out.println("The red cube is higher."); else console.out.println("The green cube is higher."); /////// // (c) /////// // Graphics context Graphics2D g = window.getBufferGraphics(); // Compute the highest and lowest point for the center of the cube double highestPositionY = c.getSize()/2; double lowestPositionY = window.getHeight() - c.getSize()/2; // start y out so the cube is up against the top of the window double y = highestPositionY; // This loop does the animation while (y <= lowestPositionY){ c.erase(g); c.moveBy(0.0, 1.0, 0.0); c.draw(g); animate(10); // do a window.repaint() and pause 10 milliseconds } ////////////// // Problem 7. ////////////// // (a) /////// Object | D | C |\ B E | A /////// // (b) /////// Potentially, we might have to look in B.java C.java D.java (Even Object.java is a possibility in general, but in this particular case we can easily check from the documentation that that there is no doSomething method in the Object class.) The reason is that instance methods can be inherited via the class hierarchy. We may find this method defined in any number of these files. We may even find it defined multiple times in any single file, but with different signatures. There can be at most one having this particular signature, which has no arguments, in each of these files. If we find a no-argument version of this method defined in more than one of these files, the one that is invoked on this B object is the one that is most specific. That is, if there is one (with no arguments) defined in the B class, it must be that one. If not, but there is one defined in the C class, it must be that one. If not, then it must be defined in the D class and that's the one that's invoked. ////////////// // Problem 8. ////////////// // (a) /////// // declare array2 and give it same size as array1 int len = array1.length; int[] array2 = new int[len]; // copy all elements of array1 into array2 except last for (int i = 0; i < len - 1; i++) array2[i+1] = array1[i]; // copy last element of array1 to beginning of array2 array2[0] = array1[len - 1]; // Could also do this in a single loop, like this: // for (int i = 0; i < len; i++) // array2[(i+1)%len] = array1[i]; /////// // (b) /////// void newPledge(){ int charityID; // get charity ID from user do{ charityID = console.in.demandInt("Enter charity ID:"); } while (charityID < 0 || charityID > 9); // should do some sanity checking here (e.g., amount should be >= 0) int amount = console.in.demandInt("Enter amount:"); // add amount to appropriate bin uw[charityID] += amount; } int showPledge(charityID){ return uw[charityID]; }