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:

• a `Runner` such as Carl Lewis or Ben Johnson, in our abstract view here, has a `name` and has always covered a certain number of `yards` (initially 0).

• the `run` method simulates a quantic way of running, more like jumping. A dice is rolled and the jump is made. But this is only because we look at the race only once every second, as if we were a radar or stroboscope of some sort.

• he code above compiles fine, but you need to finish it before it simulates a race as required by the exercise.

2. Arrays of `int`s

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:
• Can you describe what this program does?

Every time you click button `button` a new array is generated. The values are initially equal to the indices because the array starts at zero but with each push on the button the elements are changed. They are changed by adding to each element the value of the index for it.

• What's the purpose of variable `output` and how does the `TextArea` display the arrays?

This is explained in the text on pages 77-79

• What happens to the (displayed) array each time when you push the button?

Each element changes, the value of its index in the array being added to its current value.

• What's `sum()` supposed to return (as a value)?

An integer value.

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 `int`s) 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 `Runner`s

Modify the `Runner` class a little and write an application that would maintain an array of `Runner`s 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);
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;
for (int i = 0; i < athlete.length; i++) {
output += athlete[i].name + ": " +
athlete[i].distance + " yards\n";
}
} else {
// for each athlete make them advance
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 Racing();
f.setSize(400, 200);
f.setVisible(true);
}
}

class Runner {
String name;
int distance;
Runner (String givenName) {
// write this constructor
name = givenName;
distance = 0;
}
// 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);
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++)
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++)
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;
}
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.