[ Exercises | Chapter Index | Main Index ]

## Solution for Programming Exercise 4.4

This page contains a sample solution to one of the exercises from Introduction to Programming Using Java.

### Exercise 4.4:

This exercise builds on Exercise 4.3. Every time you roll the dice repeatedly, trying to get a given total, the number of rolls it takes can be different. The question naturally arises, what's the average number of rolls to get a given total? Write a function that performs the experiment of rolling to get a given total 10000 times. The desired total is a parameter to the subroutine. The average number of rolls is the return value. Each individual experiment should be done by calling the function you wrote for Exercise 4.3. Now, write a main program that will call your function once for each of the possible totals (2, 3, ..., 12). It should make a table of the results, something like:

```Total On Dice     Average Number of Rolls
-------------     -----------------------
2               35.8382
3               18.0607
.                .
.                .```

Discussion

The solution uses the subroutine, rollFor, from Exercise 4.3. That subroutine will throw an exception if its parameter is not valid. However, in my program, I know that the values that I pass to the rollFor subroutine are valid and that no exception will occur. So, there is no need to use a try..catch statement to handle the exception.

The main() program simply prints a heading for the output, then uses a for loop to compute and print the data for each of the possible rolls from 2 to 12. It is not difficult to write it, with a little care to get the formatting right (using formatted output).

The only thing left is to write a function to find the average number of rolls to get a given total on the dice. The average will be a real number, so the return type of the function is double. The subroutine has a parameter of type int that specifies the number we are rolling for. I'll call the parameter "roll". An algorithm for the subroutine is

```Let totalRolls = 0
Repeat 10000 times:
Call rollFor(roll) to run the experiment once
Add the returned value to totalRolls
Compute the average by dividing totalRolls by 10000
Return the average```

In my program, I use a named constant, NUMBER_OF_EXPERIMENTS, to specify the number of experiments to be performed. This constant replaces the value 10000, making it easier to read the program and easier to change the number of experiments if I decide I want to do more experiments or fewer. This gives the subroutine:

```public static double getAverageRollCount( int roll ) {
int rollCountThisExperiment;  // Number of rolls in one experiment.
int rollTotal;  // Total number of rolls in all the experiments.
double averageRollCount;  // Average number of rolls per experiment.
rollTotal = 0;
for ( int i = 0;  i < NUMBER_OF_EXPERIMENTS;  i++ ) {
rollCountThisExperiment = rollFor( roll );
rollTotal += rollCountThisExperiment;
}
averageRollCount = ((double)rollTotal) / NUMBER_OF_EXPERIMENTS;
return averageRollCount;
}```

Note that when the average is computed, a type-cast is used to convert rollTotal to type double. This is necessary since rollCount and NUMBER_OF_EXPERIMENTS are integers, and the computer would evaluate the quotient rollCount / NUMBER_OF_EXPERIMENTS as an integer.

By the way, this subroutine could be substantially abbreviated at the expense of being somewhat less easy to understand:

```public static double getAverageRollCount( int roll ) {
int rollTotal = 0;  // Total number of rolls in all the experiments.
for ( int i = 0;  i < NUMBER_OF_EXPERIMENTS;  i++ )
rollTotal += rollFor( roll );
return ((double)rollTotal) / NUMBER_OF_EXPERIMENTS;
}```

The Solution

```/**
* This program performs the following type of experiment:  Given a desired
* total roll, such as 7, roll a pair of dice until the given total comes up,
* and count how many rolls are necessary.  Now do that over and over, and
* find the average number of rolls.  The number of times the experiment is
* repeated is given by the constant, NUMBER_OF_EXPERIMENTS.  The average is
* computed and printed out for each possible roll = 2, 3, ..., 12.
*/

public class DiceRollStats {

/**
* The number of times that the experiment "roll for a given total"
* is to be repeated.  The program performs this many experiments, and
* prints the average of the result, for each possible roll value,
*/
public static final int NUMBER_OF_EXPERIMENTS = 10000;

public static void main(String[] args) {
double average;  // The average number of rolls to get a given total.
System.out.println("Total On Dice     Average Number of Rolls");
System.out.println("-------------     -----------------------");
for ( int dice = 2;  dice <= 12;  dice++ ) {
average = getAverageRollCount( dice );
System.out.printf("%10d%22.4f\n", dice, average);
// Use 10 spaces to output dice, and use 22 spaces to output
// average, with 4 digits after the decimal.
}
}

/**
* Find the average number of times a pair of dice must be rolled to get
* a given total.  The experiment of rolling for the given total is
* repeated NUMBER_OF_EXPERIMENTS times and the average number of rolls
* over all the experiments is computed.
* Precondition:  The given total must be between 2 and 12, inclusive.
* @param roll the total that we want to get on the dice
* @return the average number of rolls that it takes to get the specified
*    total
*/
public static double getAverageRollCount( int roll ) {
int rollCountThisExperiment;  // Number of rolls in one experiment.
int rollTotal;  // Total number of rolls in all the experiments.
double averageRollCount;  // Average number of rolls per experiment.
rollTotal = 0;
for ( int i = 0;  i < NUMBER_OF_EXPERIMENTS;  i++ ) {
rollCountThisExperiment = rollFor( roll );
rollTotal += rollCountThisExperiment;
}
averageRollCount = ((double)rollTotal) / NUMBER_OF_EXPERIMENTS;
return averageRollCount;
}

/**
* Simulates rolling a pair of dice until a given total comes up.
* Precondition:  The desired total is between 2 and 12, inclusive.
* @param N the total that we want to get on the dice
* @return the number of times the dice are rolled before the
*    desired total occurs
* @throws IllegalArgumentException if the parameter, N, is not a number
*    that could possibly come up on a pair of dice
*/
public static int rollFor( int N ) {
if ( N < 2 || N > 12 )
throw new IllegalArgumentException("Impossible total for a pair of dice.");
int die1, die2;  // Numbers between 1 and 6 representing the dice.
int roll;        // Total showing on dice.
int rollCt;      // Number of rolls made.
rollCt = 0;
do {
die1 = (int)(Math.random()*6) + 1;
die2 = (int)(Math.random()*6) + 1;
roll = die1 + die2;
rollCt++;
} while ( roll != N );
return rollCt;
}

}  // end DiceRollStats```

[ Exercises | Chapter Index | Main Index ]