Lab 2 (Jan 21-22) Solutions

Solutions are marked in blue.

For each one of the exercises below part of the code for a solution is given. This code is meant to clarify the statement of the problem and at the same time give you a jumpstart on the exercise. You may if you want come up with an entirely different solution, that doesn't use the sample code that is made available to you but that would have similar I/O behaviour.

1. Object-Oriented Olympics

Write a program Olympics.java that simulates an Olympic track and field event, a race between Carl Lewis and Ben Johnson.

In this simulation we take a snapshot every second. The program reports the distance each athlete has managed to cover. Your simulation should run for 8 seconds. With each second the player will have moved a number of yards which should be determined by rolling a fair dice (use the Math.random() routine as discussed in class and as presented in lecture notes 4).

Here's a sample run of the program (one of many, the simulation is random):

tucotuco.cs.indiana.edu% java Olympics
Seconds elapsed: 1
   Carl Lewis: advances 5 yards, reaches 5 yards.
  Ben Johnson: advances 3 yards, reaches 3 yards.
Seconds elapsed: 2
   Carl Lewis: advances 6 yards, reaches 11 yards.
  Ben Johnson: advances 6 yards, reaches 9 yards.
Seconds elapsed: 3
   Carl Lewis: advances 5 yards, reaches 16 yards.
  Ben Johnson: advances 3 yards, reaches 12 yards.
Seconds elapsed: 4
   Carl Lewis: advances 4 yards, reaches 20 yards.
  Ben Johnson: advances 2 yards, reaches 14 yards.
Seconds elapsed: 5
   Carl Lewis: advances 5 yards, reaches 25 yards.
  Ben Johnson: advances 5 yards, reaches 19 yards.
Seconds elapsed: 6
   Carl Lewis: advances 2 yards, reaches 27 yards.
  Ben Johnson: advances 6 yards, reaches 25 yards.
Seconds elapsed: 7
   Carl Lewis: advances 6 yards, reaches 33 yards.
  Ben Johnson: advances 2 yards, reaches 27 yards.
Seconds elapsed: 8
   Carl Lewis: advances 4 yards, reaches 37 yards.
  Ben Johnson: advances 6 yards, reaches 33 yards.
tucotuco.cs.indiana.edu% 
It only resembles a backgammon game, but it's an athletic race.

Here's part of the program to get you started.

tucotuco.cs.indiana.edu% cat Olympics.java
public class Olympics { public static void main(String[] args) { Runner a = new Runner(" Carl Lewis"); Runner b = new Runner("Ben Johnson"); for (int i = 1; i <= 8; i++) { System.out.println("Seconds elapsed: " + i); a.run(); b.run(); } } } class Runner { private String name; private int yards; Runner(String givenName) { name = givenName; yards = 0; } void run() { int leap; leap = (int)(Math.random() * 6 + 1); yards += leap; System.out.println(" " + name + ": advances " + leap + " yards, " + "reaches " + yards + " yards."); } }

Your job is to come up with a complete definition for the class Runner.

Things to keep in mind:

2. Arrays of ints

2.1 Generating arrays.

Using the BreezyGUI package initialize an array of 8 elements with random integers between -4 and 4. Show the array in a TextArea window element. Print the sum of the elements in the array as well. Feel free to modify the program below which does not do what the problem asks you to do but that does have the required framework:

import java.awt.*;
import BreezyGUI.*; 

public class Generate extends GBFrame {

  Button   button  = addButton  ("Click for new array!", 1, 1, 4, 1); 
  TextArea display = addTextArea(                    "", 2, 1, 3, 4); 

  int[] array = new int[8]; 
  String output; 

  public void buttonClicked(Button buttonObj) {

    output = ""; 

    for (int i = 0; i < array.length; i++) {
      // array[i] += i; 
      array[i] = (int)(Math.random() * 9) - 4;  
      output += array[i] + " "; 
    } 

    display.setText(output + "\nSum is: " + sum()); 

  }

  int sum () { 
    int runningSum; 
    for (int i = 0; i < array.length; i++) {
      runningSum += array[i]; 
    } 
    // return 0; 
    return runningSum;  
  } 

  public static void main(String[] args) {
    Frame frm = new Generate(); 
    frm.setSize(400, 200); 
    frm.setVisible(true); 
  }   

}
You will need to change a few things before you make it work, but not many. Here are a few questions to help you focus on what needs to be changed: 2.2 Looping through arrays (I)

Finding min and max

Use the program that you wrote above to calculate the largest and the smallest of the numbers in the arrays: instead of printing the sum of the elements in the array, report the largest, and the smallest, numbers in the array.

Here's the framework and part of it to get you started. (Be careful! Some parts of the program may look almost correct. Check the code carefully before using it.)

import java.awt.*;
import BreezyGUI.*; 

public class Extremes extends GBFrame {

  Button   button  = addButton  ("Click for new array!", 1, 1, 4, 1); 
  TextArea display = addTextArea(""                    , 2, 1, 3, 4); 

  int[] array = new int[8]; 
  String output; 

  public void buttonClicked(Button buttonObj) {
    output = ""; 
    for (int i = 0; i < array.length; i++) {
      array[i] = (int)(Math.random() * 9) - 4; 
      // integers in [-4, 4] are generated this way...  
      output += array[i] + " "; 
    } 
    display.setText(output + "\nMin is: " + min() 
                           + "\nMax is: " + max()); 
  }

  int min () {
    int aux = array[0]; 
    for (int i = 0; i < array.length; i++) {
      if (aux > array[i]) {         
        aux = array[i]; 
      } 
    } 
    return aux; 
  } 

  int max () {
    int aux = 0; // for the framework to compile 
                 // ...  
    aux = array[0];
    for (int i = 0; i < array.length; i++) 
      if (aux < array[i]) 
        aux = array[i];  
    return aux; 
  } 

  public static void main(String[] args) {
    Frame frm = new Extremes(); 
    frm.setSize(400, 200); 
    frm.setVisible(true); 
  }   

}
There was no mistake in the code per se, just an encouragement to look at the code carefully anyway.

Processing each element

Start from the same program that initializes an array to eight random integers between -4 and 4 (program 2.1) and make it print the array immediately after initialization and then again on the next line with all the negative integers replaced with their absolute value (or surrounded by square brackets, your pick).

for (int i = 0; i < array.length; i++) {
  output = ""; 
  array[i] = (int)(Math.random() * 9) - 4; 
  output += array[i] + "  "; 
} 
output += "\n";
for (int i = 0; i < array.length; i++) {
  if (array[i] > 0) 
    output += array[i] + "  "; 
  else 
    output += "[" + ( -array[i] ) + "] "; 
}

Summing only some of the elements

Combine the programs that you have developed so far to produce the sum of those numbers in the array that are both positive and divisible with 3. Increase the range of the values that the elements in the array can have from [-4, 4] to [-10, 10]. Use the modulus operator (%) to resolve divisibility questions.

for (int i = 0; i < array.length; i++) {
  output = ""; 
  array[i] = (int)(Math.random() * 21) - 10; 
  output += array[i] + "  "; 
} 
int sum = 0;
for (int i = 0; i < array.length; i++) {
  if (array[i] > 0 && array[i] % 3 == 0) 
    sum += array[i];  
}
output += "Sum = " + sum + "\n";

Summing every other element

Rewrite the program at 2.1 (8-element array of ints) such that the sum computed adds the numbers in the array starting with the first (at index 0) and skipping every other element. Use a for loop.

int sum = 0;
for (int i = 0; i < array.length; i+=2) {
    sum += array[i];
}

3. Arrays of Runners

Modify the Runner class a little and write an application that would maintain an array of Runners that keep advancing each time the "Advance" button is pressed. The results are shown in a TextArea field. There is also a "Start" button, that initializes a race to an array of athletes starting at 0, the number of athletes in the race being specified by the user in an IntegerField.

If the "Advance" button is pressed before the "Start" button initialize the array first and the race, otherwise pressing "Advance" ignores the value in the IntegerField.

You may find the following framework useful:

import java.awt.*; 
import BreezyGUI.*;

public class Racing extends GBFrame {
  Button        b = addButton(       "Start", 1, 1, 1, 1); 
  Button        c = addButton(     "Advance", 1, 2, 1, 1); 
  Label         m = addLabel ("No. athletes", 1, 3, 1, 1); 
  IntegerField  i = addIntegerField(       2, 1, 4, 1, 1); 
  TextArea      t = addTextArea(          "", 2, 1, 4, 4); 
  Runner[] athlete; 
  boolean initialized = false; 
  public void buttonClicked (Button buttonObj) {
    int n = i.getNumber(); String output = ""; 
    if (buttonObj == b) { 
      // initialize the race  
      athlete = new Runner[n]; 
      for (int i = 0; i < athlete.length; i++) {
        athlete[i] = new Runner("Runner " + i); 
        output += athlete[i].name + ": " + 
                  athlete[i].distance + " yards\n"; 
      }  
      initialized = true; 
    } else { 
      // advance one step in the race 
      // if the race has not been initialized yet 
      if (initialized == false) {  
        //   initialize it now  
        athlete = new Runner[n]; 
        for (int i = 0; i < athlete.length; i++) {
          athlete[i] = new Runner("Runner " + i); 
        } 
        initialized = true; 
        // then advance one step 
        for (int i = 0; i < athlete.length; i++) { 
          athlete[i].advance(); 
          output += athlete[i].name + ": " + 
                    athlete[i].distance + " yards\n"; 
        }         
      } else {  
        // for each athlete make them advance  
        for (int i = 0; i < athlete.length; i++) { 
          athlete[i].advance(); 
          output += athlete[i].name + ": " + 
                    athlete[i].distance + " yards\n"; 
        } 
      }   
    } 
    // by now output should display the current situation 
    // in the race, formatted for display, one athlete per line 
    t.setText(output); 
  } 
  public static void main(String[] args) {
    Frame f = new Racing(); 
    f.setSize(400, 200); 
    f.setVisible(true); 
  } 
} 

class Runner {
  String name;
  int distance;
  Runner (String givenName) {
    // write this constructor 
    name = givenName; 
    distance = 0;  
  } 
  void advance() {
    // write this method 
    int leap; 
    leap = (int)(Math.random() * 6 + 1); 
    distance += leap;  
  } 
}

For the ambitious: knowing that the following snippet of code can be used to sort an array of integers in descending order

boolean done = false; 
while (! done) { 
  int aux; 
  done = true;
  for (int i = 0; i < array.length - 1; i++) {
    if (array[i] < array[i+1]) {
      aux = array[i];
      array[i] = array[i + 1]; 
      array[i + 1] = aux; 
      done = false; 
    } 
  } 
} 
modify the program to see the current status in the race such that the athletes are sorted in descending order based on the distance covered so far. Here's another sorting program based on the approach discussed in class on Thursday.

public class Sort {
  public static void main(String[] args) {
    int[] a = { 8, 7, 6, 5, 4, 3, 2, 1}; 
    boolean sorted; // sorted needs to be declared here to 
    // be available in the condition for while. The scope 
    // of the do-while block does not include the condition! 
    do { int aux; 
      sorted = true; 
      for (int i = 0; i < a.length - 1; i++) {
        if (a[i] > a[i+1]) { sorted = false;
          aux = a[i]; a[i] = a[i+1]; a[i+1] = aux;  
        } 
      } 
    } while (! sorted); 
    for (int i = 0; i < a.length; i++) {
      System.out.println(i); 
    } 
  } 
}

Here's the solution for the ambitious, with not many comments.

It uses the first method of sorting, BubbleSort.

import java.awt.*; 
import BreezyGUI.*;

public class SortedRacing extends GBFrame {
  Button        b = addButton(       "Start", 1, 1, 1, 1); 
  Button        c = addButton(     "Advance", 1, 2, 1, 1); 
  Label         m = addLabel ("No. athletes", 1, 3, 1, 1); 
  IntegerField  i = addIntegerField(       2, 1, 4, 1, 1); 
  TextArea      t = addTextArea(          "", 2, 1, 4, 4); 
  Runner[] athlete;  
  void sort() {
    boolean done = false; 
    while (! done) { 
      Runner aux; 
      done = true;
      for (int i = 0; i < athlete.length - 1; i++) {
        if (athlete[i].distance < athlete[i+1].distance) {
          aux = athlete[i];
          athlete[i] = athlete[i + 1]; 
          athlete[i + 1] = aux; 
          done = false; 
        } 
      } 
    } 
  }  
  boolean initialized = false; 
  public void buttonClicked (Button buttonObj) {
    int n = i.getNumber(); String output = ""; 
    if (buttonObj == b) {  
      athlete = new Runner[n]; 
      for (int i = 0; i < athlete.length; i++) {
        athlete[i] = new Runner("Runner " + i); 
        output += athlete[i].name + ": " + 
                  athlete[i].distance + " yards\n"; 
      }  
      initialized = true; 
    } else { 
      if (initialized == false) {  
        athlete = new Runner[n]; 
        for (int i = 0; i < athlete.length; i++) 
          athlete[i] = new Runner("Runner " + i); 
        initialized = true; 
        for (int i = 0; i < athlete.length; i++) 
          athlete[i].advance(); 
        sort(); 
        // notice this splits the original for loop in two loops 
        // one for the advance step and the other one for output 
        for (int i = 0; i < athlete.length; i++) 
          output += athlete[i].name + ": " + 
                    athlete[i].distance + " yards\n"; 
      } else {  
        for (int i = 0; i < athlete.length; i++)
          athlete[i].advance(); 
        sort(); // same comment as above  
        for (int i = 0; i < athlete.length; i++) 
          output += athlete[i].name + ": " + 
                    athlete[i].distance + " yards\n";         
      }   
    } 
    // by now output should display the current situation 
    // in the race, formatted for display, one athlete per line 
    t.setText(output); 
  } 
  public static void main(String[] args) {
    Frame f = new SortedRacing(); 
    f.setSize(400, 200); 
    f.setVisible(true); 
  } 
} 

class Runner {
  String name;
  int distance;
  // if we make distance private we need an accessor 
  // method to do the sorting by the distance covered
  Runner (String givenName) {
    name = givenName; 
    distance = 0;  
  } 
  void advance() {
    int leap; 
    leap = (int)(Math.random() * 6 + 1); 
    distance += leap;  
  } 
}

4. Experimental probabilities

Write a program that simulates throwing a dice for a number of times. The integer values that you obtain should be 1, 2, 3, 4, 5, and 6. Each occurrence for each of these integers should be counted in a corresponding element of an array with 6 elements. At the end of each simulation write down (output) the number of times each of the six integers has come out. For example throwing the dice 600 times could produce the following distribution of frequencies:

[1]: 91
[2]: 97
[3]: 102
[4]: 99
[5]: 109
[6]: 102
If you're making several simulations in a row be sure to start with the array of frequencies fresh (that is, initialized at 0). Here's part of the program to get you started. Of course, the most important part is missing:
import java.awt.*; 
import BreezyGUI.*;

public class Probabilities extends GBFrame {
  Button        b = addButton(       "Start", 1, 1, 1, 1); 
  IntegerField  i = addIntegerField(       0, 1, 2, 1, 1); 
  TextArea      t = addTextArea(          "", 2, 1, 3, 4); 
  int[] bins = new int[6]; 
  public void buttonClicked (Button buttonObj) {
    int n = i.getNumber(); String output = ""; 
    for (int i = 0; i < bins.length; i++) bins[i] = 0; 
    for (int i = 0; i < n; i++) {
      bins[(int)(Math.random() * 6)] += 1; 
    } 
    for (int i=0; i < 6; i++) { 
      output += "[" + (i + 1) + "]: " + bins[i] + "\n"; 
    }  
    t.setText(output); 
  } 
  public static void main(String[] args) {
    Frame f = new Probabilities(); 
    f.setSize(400, 200); 
    f.setVisible(true); 
  } 
}
The part that you need to write goes into buttonClicked. Try both approaches discussed in class: try rounding the values that you obtain from Math.random() and try flooring them. See how the distributions change shape accordingly.