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 ]