How do you design a rand7 function using a rand5 function?
My solution is:
def rand7(): n = rand5() + rand5() + rand5() + rand5() + rand5() + rand5() + rand5() + rand5() return n%8
Firstly, is the correct? Second, either way provide additional ways of accomplishing this. Thanks!
Update: 10000000 simulations resulted in the following results
0 had count 1250972 Chance: 12.50972% 1 had count 1251284 Chance: 12.51284% 2 had count 1248768 Chance: 12.48768% 3 had count 1251610 Chance: 12.5161% 4 had count 1250475 Chance: 12.50475% 5 had count 1249196 Chance: 12.49196% 6 had count 1249427 Chance: 12.49427% 7 had count 1248268 Chance: 12.48268%
5 Answers
Rand7 is supposed to turn one of 7 numbers (0 through 6 OR 1 through 7). Rand5 returns one of 5 numbers. For my explanation, I've assumed that rand7 returns 0 through 6.
There is no deterministic way of doing this [see explanation below]. By "deterministic" we mean that there is no way of doing this such that you can GUARANTEE that the program will return within X calls to rand. So, no, your solution does not work since it is deterministic.
How can you solve it? You'll have to do it with a loop that could, theoretically, loop for a very long time.
Here's one simple way:
In other words, we're doing this:
Why there's no deterministic solution
Suppose there were a deterministic way of doing this. This means that you are guaranteeing me that within X calls max to rand5, you can randomly generate a number between 0 and 6 with equal probability.
Wonderful. Okay.
Observe that:
So, now, we basically have a rand7 program that calls rand5 exactly X times. The results of those calls will determine what the value for rand7.
You can treat the sequence of results for rand5 as a string if you'd like. So, 013 means to get a 0 on the first call, then a 1, then a 3.
How many strings could you make? Well, X slots. 5 possibilities for each slot. So, there are 5^X slots.
Following me so far? Excellent!
Now then. I'd like you to divide those 5^X strings into 7 equal buckets.
What, you can't do that? Because 7 doesn't go into 5^X equally?
Oh.
Guess your deterministic rand7 program isn't so equally random after all.
There is no deterministic way of doing this [see explanation below]. By "deterministic" we mean that there is no way of doing this such that you can GUARANTEE that the program will return within X calls to rand. So, no, your solution does not work since it is deterministic.
How can you solve it? You'll have to do it with a loop that could, theoretically, loop for a very long time.
Here's one simple way:
- Call rand5 until you get a number between 0 and 3 (that is, anything but 4). Set b0 (bit 0) to that number % 2. So b0 is 0 if rand5 was 0 or 2, and 1 otherwise.
- Do the same for bit 1 and bit 2.
- We now have a 3 bit number -- which will be a number between 0 and 7.
- If that number is a 7, start over. Else, return.
In other words, we're doing this:
int rand2() {
int x = rand5();
if x == 4 return rand2(); // restart
else return x % 2;
}
int rand7() {
int x = rand2() * 4 + rand2() * 2 + rand2();
if (x == 7) return rand7(); // restart
else return x;
}
Why there's no deterministic solution
Suppose there were a deterministic way of doing this. This means that you are guaranteeing me that within X calls max to rand5, you can randomly generate a number between 0 and 6 with equal probability.
Wonderful. Okay.
Observe that:
- If you run the rand7 program twice, and you get the same results both times for each rand5 call, you'll get the same result for the rand7 program.
- Some "paths" through the program might call rand5 fewer than X times. However, for the purposes we can treat this as still calling rand5 X times, where it just doesn't use those results.
So, now, we basically have a rand7 program that calls rand5 exactly X times. The results of those calls will determine what the value for rand7.
You can treat the sequence of results for rand5 as a string if you'd like. So, 013 means to get a 0 on the first call, then a 1, then a 3.
How many strings could you make? Well, X slots. 5 possibilities for each slot. So, there are 5^X slots.
Following me so far? Excellent!
Now then. I'd like you to divide those 5^X strings into 7 equal buckets.
What, you can't do that? Because 7 doesn't go into 5^X equally?
Oh.
Guess your deterministic rand7 program isn't so equally random after all.