### Solution for

Programming Exercise 4.4

THIS PAGE DISCUSSES ONE POSSIBLE SOLUTION to
the following exercise from this on-line
Java textbook.

**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?
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
the previous exercise.

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 litte care to get the
formatting right.

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:

static double getAverageRollCount( int roll ) {
// Find the average number of times a pair of dice must
// be rolled to get a total of "roll". Roll MUST be
// one of the numbers 2, 3, ..., 12.
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;
}

It is important that `roll` be in the range
of possible totals on a pair of dice. If it is not, the program will
enter an infinite loop in the `rollFor()` subroutine.

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:

static double getAverageRollCount( int roll ) {
// Find the average number of times a pair of dice must
// be rolled to get a total of "roll". Roll MUST be
// one of the numbers 2, 3, ..., 12.
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**

public class DiceRollStats {
/*
This program preforms 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 the 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.
*/
static final int NUMBER_OF_EXPERIMENTS = 10000;
public static void main(String[] args) {
// Find the average number of times a pair of dice has
// to be rolled to get a given total. Do this for
// each possible total roll, 2 through 12, and print
// the results.
double average; // The average number of rolls to get a given total.
TextIO.putln("Total On Dice Average Number of Rolls");
TextIO.putln("------------- -----------------------");
for ( int dice = 2; dice <= 12; dice++ ) {
average = getAverageRollCount( dice );
TextIO.put(dice,10);
TextIO.put(" ");
TextIO.putln(average);
}
}
static double getAverageRollCount( int roll ) {
// Find the average number of times a pair of dice must
// be rolled to get a total of "roll". Roll MUST be
// one of the numbers 2, 3, ..., 12.
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;
}
static int rollFor( int N ) {
// Roll a pair of dice repeatedly until the total on the
// two dice comes up to be N. N MUST be one of the numbers
// 2, 3, ..., 12. (If not, this routine will go into an
// infinite loop!). The number of rolls is returned.
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
]