Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

From 5 dice rolls, generate a random number in the range [1 - 100]

I was going through some coding exercises, and had some trouble with this question:

From 5 dice (6-sided) rolls, generate a random number in the range [1 - 100].

I implemented the following method, but the returned number is not random (called the function 1,000,000 times and several numbers never show up in 1 - 100).

public static int generator() {

     Random rand = new Random();
     int dices = 0;

     for(int i = 0; i < 5; i++) {
         dices += rand.nextInt(6) + 1;
     }

     int originalStart = 5;
     int originalEnd = 30;
     int newStart = 1;
     int newEnd = 100;

     double scale = (double) (newEnd - newStart) / (originalEnd - originalStart);
     return (int) (newStart + ((dices - originalStart) * scale));
}
like image 975
yohm Avatar asked Sep 03 '14 23:09

yohm


2 Answers

Ok, so 5 dice rolls, each with 6 options. if they are un-ordered you have a range of 5-30 as mentioned above - never sufficient for 1-100.

You need to assume an order, this gives you a scale of 1,1,1,1,1 - 6,6,6,6,6 (base 6) assuming 1 --> 0 value, you have a 5 digit base 6 number generated. As we all know 6^5 = 7776 unique possibilities. ;)

For this I am going to give you a biased random solution.

int total = 0;
int[] diceRolls;
for (int roll : diceRolls) {
    total = total*6 + roll - 1;
}

return total % 100 + 1;

thanks to JosEdu for clarifying bracket requirement

Also if you wanted to un-bias this, you could divide range by the maxval given in my description above, and subsequently multiply by your total (then add offset), but you would still need to determine what rounding rules you used.

like image 169
Guy Flavell Avatar answered Sep 29 '22 20:09

Guy Flavell


The problem is there aren't enough random values in 5-30 to map one to one to 1-100 interval. This means certain values are destined to never show up; the amount of these "lost" values depends on the size ratio of the two intervals.

You can leverage the power of your dice in a way more efficient way, however. Here's how I'd do it:

Approach 1

  1. Use the result of the first dice to choose one subinterval from the 6 equal subintervals with size 16.5 (99/6).
  2. Use the result of the second dice to choose one subinterval from the 6 equal sub-subintervals of the subinterval you chose in step one.
  3. Use... I guess you know what follows next.

Approach 2

Construct your random number using digits in a base-6 system. I.E. The first dice will be the first digit of the base-6 number, the second dice - the second digit, etc.
Then convert to base-10, and divide by (46656/99). You should have your random number. You could in fact only use 3 dice, of course, the rest two are just redundant.

like image 38
Slavic Avatar answered Sep 29 '22 20:09

Slavic