import java.text.NumberFormat;

import java.lang.String; /*

** All the number crunching is in this class.

** I/O, Events and formatting are in the other file.

** Implementation of the 3 loop method with protections

** to prevent unneeded rebuilding of the main array.

*/ public class DiceStuff { /* ** Maximum sizes of dice to prevent math overflow and limit memory use. */ static final int max_sides = 15 ; static final int max_dice = 15 ; static final int max_roll = max_sides * max_dice ; /* ** The main array. */ static long wayray[][] = new long[max_dice + 1][max_roll + 1] ; /* ** Flags to indicate how many sides the array is currently using... ** and the max number of dice the array is currently initialized to handle. */ static int way_ray_sides = 0 ; static int way_ray_filled = 0 ; /* ** Tis a shame to have a constructor with nothing to construct. ** A non-static variable just for the heck of it. */ int waste ; /* ** In an object oriented language, you need an object to manipulate ** before one can call code to do anything. This is a "constructor" ** class which returns an instance of DiceStuff so that the DiceStuff ** public procedures can be accessed. */ public DiceStuff() { waste = 1 ; } /* ** Initializes the static array which holds all the numbers. ** Up to date using correct dice size and up to the requested ** number of dice. */ private void initwayray(int count_in, int sides_in) { /* How much of the matrix has to be rebuilt. */ int first_rebuild ; int last_rebuild ; /* Scratch variables used in the rebuilding. */ int build_this ; int last_min ; int last_max ; int target_sum ; int from_index ; int to_index ; long adding_this ; if (way_ray_sides != sides_in) { /* ** Operator changed dice sizes. ** Nothing we have is any good. ** Start from the beginning. */ first_rebuild = 1 ; last_rebuild = count_in ; /* ** Save current state of the array for next time. */ way_ray_sides = sides_in ; way_ray_filled = count_in ; /* ** Assume 1 way to roll ** a zero on zero dice. ** Otherwise, table for 1 dice doesn't build right. */ wayray[0][0] = 1 ; } else if ( count_in > way_ray_filled) { /* ** Array partially built. ** Keep what is already built. ** Add on more dice. */ first_rebuild = way_ray_filled + 1 ; last_rebuild = count_in ; /* ** Remember what was built so we don't have to build it ** again next time. */ way_ray_filled = count_in ; } else { /* ** Same size dice. ** Same number or fewer dice. ** Table is already good enough. ** No need to rebuild. */ return ; } /* ** What columns have we got to build? ** Loop through each column. */ for (build_this = first_rebuild ; build_this <= last_rebuild ; build_this++) { /* ** Clear any old contents in the rebuilding row. */ for (to_index = 0 ; to_index < max_roll ; to_index++) { wayray[build_this][to_index] = 0 ; } /* ** What is the range of non-zero results in prior existing row? ** Each old content must be added into sides_in new entries ** in the row we are building. */ last_min = (build_this - 1) ; last_max = (build_this - 1) * sides_in ; /* ** Loop through the last row, adding contents into new row. */ for ( from_index = last_min ; from_index <= last_max ; from_index++ ) { /* ** This number has to be added to a bunch of numbers in the ** new column. */ adding_this = wayray[build_this - 1][from_index] ; /* ** Which new numbers must be added to? ** Let us set up the loop. */ for (to_index = from_index + 1 ; to_index <= from_index + sides_in ; to_index++) { wayray[build_this][to_index] += adding_this ; } } } } /* ** Returns number of ways to hit target. ** Checks range. ** Makes sure way ray is up to date. ** Returns ways to role this target on count dice ** with sides sides. */ public long intwayray(int count, int sides, int target) { /* Range check. */ if (( sides > max_sides) || (count > max_dice) || (target > max_roll)) { return 0 ; } /* Bring statistic array up to date. */ initwayray(count, sides) ; /* Ways to roll this number */ long ways_to_roll = wayray[count][target] ; return ways_to_roll ; } /* ** Returns the sum of the ways to roll all of the numbers ** less than or equal to target. */ public long sumwayray(int count_in, int sides, int target) { long sum = 0 ; int index ; /* Range check. */ if (( sides > max_sides) || (count_in > max_dice) || (target > max_roll)) { return 0 ; } /* Bring statistic array up to date. */ initwayray(count_in, sides) ; for (index = count_in ; index <= target ; index++) { sum += wayray[count_in][index] ; } return sum ; } }