Reputation: 515
This question was asked in my interview. random(0,1) is a function that generates integers 0 and 1 randomly. Using this function how would you design a function that takes two integers a,b as input and generates random integers including a and b.
I have No idea how to solve this.
Upvotes: 3
Views: 413
Reputation: 870
function randomBetween(int a, int b){
int x = b-a;//assuming a is smaller than b
float rand = random();
return a+Math.ceil(rand*x);
}
Upvotes: 0
Reputation: 2102
So we have randomBit()
returning 0 or 1 independently, uniformly at random and we want a function random(a, b)
that returns a value in the range [a,b]
uniformly at random. Let's actually make that the range [a, b)
because half-open ranges are easier to work with and equivalent. In fact, it is easy to see that we can just consider the case where a == 0
(and b > 0
), i.e. we just want to generate a random integer in the range [0, b)
.
Let's start with the simple answer suggested elsewhere. (Forgive me for using c++ syntax, the concept is the same in Java)
int random2n(int n) {
int ret = n ? randomBit() + (random2n(n - 1) << 1) : 0;
}
int random(int b) {
int n = ceil(log2(b)), v;
while ((v = random2n(n)) >= b);
return v;
}
That is-- it is easy to generate a value in the range [0, 2^n)
given randomBit()
. So to get a value in [0, b)
, we repeatedly generate something in the range [0, 2^ceil(log2(b))]
until we get something in the correct range. It is rather trivial to show that this selects from the range [0, b)
uniformly at random.
As stated before, the worst case expected number of calls to randomBit()
for this is (1 + 1/2 + 1/4 + ...) ceil(log2(b)) = 2 ceil(log2(b))
. Most of those calls are a waste, we really only need log2(n)
bits of entropy and so we should try to get as close to that as possible. Even a clever implementation of this that calculates the high bits early and bails out as soon as it exits the wanted range has the same expected number of calls to randomBit()
in the worst case.
We can devise a more efficient (in terms of calls to randomBit()
) method quite easily. Let's say we want to generate a number in the range [0, b)
. With a single call to randomBit()
, we should be able to approximately cut our target range in half. In fact, if b
is even, we can do that. If b
is odd, we will have a (very) small chance that we have to "re-roll". Consider the function:
int random(int b) {
if (b < 2) return 0;
int mid = (b + 1) / 2, ret = b;
while (ret == b) {
ret = (randomBit() ? mid : 0) + random(mid);
}
return ret;
}
This function essentially uses each random bit to select between two halves of the wanted range and then recursively generates a value in that half. While the function is fairly simple, the analysis of it is a bit more complex. By induction one can prove that this generates a value in the range [0, b)
uniformly at random. Also, it can be shown that, in the worst case, this is expected to require ceil(log2(b)) + 2
calls to randomBit()
. When randomBit()
is slow, as may be the case for a true random generator, this is expected to waste only a constant number of calls rather than a linear amount as in the first solution.
Upvotes: 0
Reputation: 22890
I hate this kind of interview Question because there are some answer fulfilling it but the interviewer will be pretty mad if you use them. For example,
Call random,
if you obtain 0, output a
if you obtain 1, output b
A more sophisticate answer, and probably what the interviewer wants is
init(a,b){
c = Max(a,b)
d = log2(c) //so we know how much bits we need to cover both a and b
}
Random(){
int r = 0;
for(int i = 0; i< d; i++)
r = (r<<1)| Random01();
return r;
}
You can generate random strings of 0 and 1 by successively calling the sub function.
Upvotes: 0
Reputation: 3928
We can do this easily by bit logic (E,g, a=4 b=10)
Upvotes: 4