Where is my logic going wrong which involves multiplying by two and subtracting by one to obtain a given number? - algorithm

http://codeforces.com/contest/520/problem/B
Vasya has found a strange device. On the front panel of a device there are: a red button, a blue button and a display showing some positive integer. After clicking the red button, device multiplies the displayed number by two. After clicking the blue button, device subtracts one from the number on the display. If at some point the number stops being positive, the device breaks down. The display can show arbitrarily large numbers. Initially, the display shows number n.
Bob wants to get number m on the display. What minimum number of clicks he has to make in order to achieve this result?
Input
The first and the only line of the input contains two distinct integers n and m (1 ≤ n, m ≤ 10^4), separated by a space .
Output
Print a single number — the minimum number of times one needs to push the button required to get the number m out of number n.
I developed the following recursive solution. I know it will time out, but I will memoise it, and that will get my solution accepted. But as of now, I am getting a wrong answer in one of the inputs.
My code is:
int func (int n, int m);
int main (void)
{
int n,m;
cin>>n>>m;
int count = func(n,m);
cout<<count<<"\n";
return 0;
}
int func (int n, int m)
{
if (n == 0)
return INT_MAX; // this should be because we can never go to some
// other digit if we are at 0
if (n == m)
return 0;
else if (2*n == m || n == m+1)
return 1;
else if (n > m)
return func(n-1,m)+1;
else
return min(func(n-1,m),func(n*2,m))+1;
}
Now, when I enter the input as (1,3), my code shows Segmentation fault. I tried to debug it, and I found out that it sorts of go in an infinite loop because of which I get the Seg fault. However, I want to know, then how should I make the logic for this? What will be the recursive function for this? Thanks!

The SEG fault is due to calculating doing INT_MAX+1.
Actually I think this problem is better solved working this way.
For all cases n>m, the shortest count is n-m.
if (n<m)
return n-m;
For all cases n==m, the shortest count is 0.
else if (n==m)
return 0;
For all cases n < m, the shortest count can be calculated as:
let sequence Y= [(m/(2^1), m/(2^2), ... 1] // use the ceiling values
find X is the next number in the Y where n >= X.
return func(X*2) + n-X + 1;
For n = 57, m = 201, then Y = [101, 51, 26, 13, 7, 4, 2, 1], X would be 51.
So the answer can be calculated as
(57-51)+1 = 7 steps, result now 51*2 = 102
(102-101)+1 = 2 steps, result now 101*2 = 202
(202-201) = 1 steps
=====> Total steps 10
For n = 4, m = 6, then Y = [3, 2, 1], X would be 3.
So the answer can be calculated as
(4-3)+1 = 2 steps, result now 3*2=6
=====> Total steps 2
For n = 1, m = 3, then Y = [2, 1], X would be 1.
So the answer can be calculated as
already in Y= 1 steps, result now 1*2 = 2
already in Y= 1 steps, result now 2*2 = 4
(4-3) = 1 step
=====> Total steps 3
Notice you can precalcuate Y before entering your function and pass it in so you don't have to recompute each time.

Related

Given an array of numbers. At each step we can pick a number like N in this array and sum N with another number that exist in this array

I'm stuck on this problem.
Given an array of numbers. At each step we can pick a number like N in this array and sum N with another number that exist in this array. We continue this process until all numbers in this array equals to zero. What is the minimum number of steps required? (We can guarantee initially the sum of numbers in this array is zero).
Example: -20,-15,1,3,7,9,15
Step 1: pick -15 and sum with 15 -> -20,0,1,3,7,9,0
Step 2: pick 9 and sum with -20 -> -11,0,1,3,7,0,0
Step 3: pick 7 and sum with -11 -> -4,0,1,3,0,0,0
Step 4: pick 3 and sum with -4 -> -1,0,1,0,0,0,0
Step 5: pick 1 and sum with -1 -> 0,0,0,0,0,0,0
So the answer of this example is 5.
I've tried using greedy algorithm. It works like this:
At each step we pick maximum and minimum number that already available in this array and sum these two numbers until all numbers in this array equals to zero.
but it doesn't work and get me wrong answer. Can anyone help me to solve this problem?
#include <bits/stdc++.h>
using namespace std;
int a[] = {-20,-15,1,3,7,9,15};
int bruteforce(){
bool isEqualToZero = 1;
for (int i=0;i<(sizeof(a)/sizeof(int));i++)
if (a[i] != 0){
isEqualToZero = 0;
break;
}
if (isEqualToZero)
return 0;
int tmp=0,m=1e9;
for (int i=0;i<(sizeof(a)/sizeof(int));i++){
for (int j=i+1;j<(sizeof(a)/sizeof(int));j++){
if (a[i]*a[j] >= 0) continue;
tmp = a[j];
a[i] += a[j];
a[j] = 0;
m = min(m,bruteforce());
a[j] = tmp;
a[i] -= tmp;
}
}
return m+1;
}
int main()
{
cout << bruteforce();
}
This is the brute force approach that I've written for this problem. Is there any algorithm to solve this problem faster?
This has an np-complete feel, but the following search does an A* search through all possible normalized partial sums on the way to a single non-zero term. Which solves your problem, and means that you don't get into an infinite loop if the sum is not zero.
If greedy works, this will explore the greedy path first, verify that you can't do better, and return fairly quickly. If greedy doesn't work, this may...take a lot longer.
Implementation in Python because that is easy for me. Translation into another language is an exercise for the reader.
import heapq
def find_minimal_steps (numbers):
normalized = tuple(sorted(numbers))
seen = set([normalized])
todo = [(min_steps_remaining(normalized), 0, normalized, None)]
while todo[0][0] < 7:
step_limit, steps_taken, prev, path = heapq.heappop(todo)
steps_taken = -1 * steps_taken # We store negative for sort order
if min_steps_remaining(prev) == 0:
decoded_path = []
while path is not None:
decoded_path.append((path[0], path[1]))
path = path[2]
return steps_taken, list(reversed(decoded_path))
prev_numbers = list(prev)
for i in range(len(prev_numbers)):
for j in range(len(prev_numbers)):
if i != j:
# Track what they were
num_i = prev_numbers[i]
num_j = prev_numbers[j]
# Sum them
prev_numbers[i] += num_j
prev_numbers[j] = 0
normalized = tuple(sorted(prev_numbers))
if (normalized not in seen):
seen.add(normalized)
heapq.heappush(todo, (
min_steps_remaining(normalized) + steps_taken + 1,
-steps_taken - 1, # More steps is smaller is looked at first
normalized,
(num_i, num_j, path)))
# set them back.
prev_numbers[i] = num_i
prev_numbers[j] = num_j
print(find_minimal_steps([-20,-15,1,3,7,9,15]))
For fun I also added a linked list implementation that doesn't just tell you how many minimal steps, but which ones it found. In this case its steps were (-15, 15), (7, 9), (3, 16), (1, 19), (-20, 20) meaning add 15 to -15, 9 to 7, 16 to 3, 19 to 1, and 20 to -20.

Maximum sum increasing subsequence, changing algorithm to use memoization

I have the following code which implements a recursive solution for this problem, instead of using the reference variable 'x' to store overall max, How can I or can I return the result from recursion so I don't have to use the 'x' which would help memoization?
// Test Cases:
// Input: {1, 101, 2, 3, 100, 4, 5} Output: 106
// Input: {3, 4, 5, 10} Output: 22
int sum(vector<int> seq)
{
int x = INT32_MIN;
helper(seq, seq.size(), x);
return x;
}
int helper(vector<int>& seq, int n, int& x)
{
if (n == 1) return seq[0];
int maxTillNow = seq[0];
int res = INT32_MIN;
for (int i = 1; i < n; ++i)
{
res = helper(seq, i, x);
if (seq[i - 1] < seq[n - 1] && res + seq[n - 1] > maxTillNow) maxTillNow = res + seq[n - 1];
}
x = max(x, maxTillNow);
return maxTillNow;
}
First, I don't think this implementation is correct. For this input {5, 1, 2, 3, 4} it gives 14 while the correct result is 10.
For writing a recursive solution for this problem, you don't need to pass x as a parameter, as x is the result you expect to get from the function itself. Instead, you can construct a state as the following:
Current index: this is the index you're processing at the current step.
Last taken number: This is the value of the last number you included in your result subsequence so far. This is to make sure that you pick larger numbers in the following steps to keep the result subsequence increasing.
So your function definition is something like sum(current_index, last_taken_number) = the maximum increasing sum from current_index until the end, given that you have to pick elements greater than last_taken_number to keep it an increasing subsequence, where the answer that you desire is sum(0, a small value) since it calculates the result for the whole sequence. by a small value I mean smaller than any other value in the whole sequence.
sum(current_index, last_taken_number) could be calculated recursively using smaller substates. First assume the simple cases:
N = 0, result is 0 since you don't have a sequence at all.
N = 1, the sequence contains only one number, the result is either that number or 0 in case the number is negative (I'm considering an empty subsequence as a valid subsequence, so not taking any number is a valid answer).
Now to the tricky part, when N >= 2.
Assume that N = 2. In this case you have two options:
Either ignore the first number, then the problem can be reduced to the N=1 version where that number is the last one in the sequence. In this case the result is the same as sum(1,MIN_VAL), where current_index=1 since we already processed index=0 and decided to ignore it, and MIN_VAL is the small value we mentioned above
Take the first number. Assume the its value is X. Then the result is X + sum(1, X). That means the solution includes X since you decided to include it in the sequence, plus whatever the result is from sum(1,X). Note that we're calling sum with MIN_VAL=X since we decided to take X, so the following values that we pick have to be greater than X.
Both decisions are valid. The result is whatever the maximum of these two. So we can deduce the general recurrence as the following:
sum(current_index, MIN_VAL) = max(
sum(current_index + 1, MIN_VAL) // ignore,
seq[current_index] + sum(current_index + 1, seq[current_index]) // take
).
The second decision is not always valid, so you have to make sure that the current element > MIN_VAL in order to be valid to take it.
This is a pseudo code for the idea:
sum(current_index, MIN_VAL){
if(current_index == END_OF_SEQUENCE) return 0
if( state[current_index,MIN_VAL] was calculated before ) return the perviously calculated result
decision_1 = sum(current_index + 1, MIN_VAL) // ignore case
if(sequence[current_index] > MIN_VAL) // decision_2 is valid
decision_2 = sequence[current_index] + sum(current_index + 1, sequence[current_index]) // take case
else
decision_2 = INT_MIN
result = max(decision_1, decision_2)
memorize result for the state[current_index, MIN_VAL]
return result
}

Unable to understand algorithm

Here is the link of problem
https://www.hackerrank.com/challenges/equal
I read its editorial and unable to understand it. And if you are not make any account on hackerrank then surely you will not see it's editorial so here is some lines of editorial.
This is equivalent to saying, christy can take away the chocolates of
one coworker by 1, 2 or 5 while keeping others' chocolate untouched.
Let's consider decreasing a coworker's chocolate as an operation. To minimize the number of operations, we should try to make the number of chocolates of every coworker equal to the minimum one in the group(min). We have to decrease the number of chocolates the ith person A[i] by (A[i] - min). Let this value be x.
This can be done in k operations.
k = x/5 +(x%5)/2 + (x%5)%2
and from here i unable to understand
Let f(min) be sum of operations performed over all coworkers to reduce
each of their chocolates to min. However, sometimes f(min) might not
always give the correct answer. It can also be a case when
f(min) > f(min-1)
f(min) < f(min-5)
as f(min-5) takes N operations more than f(min) where N is the number
of coworkers. Therefore, if
A = {min,min-1,min-2,min-3,min-4}
then f(A) <= f(min) < f(min-5)
can someone help me to understand why this is necessary to check f(min),f(min-1),...,f(min-4)
Consider the case A = [1,5,5]
As the editorial said, it is intuitive to think it is optimal to change A to [1,1,1] with 4 (2 minus 2) operations, but it is better to change it to [0,0,0] with 3 (1 minus 1, 2 minus 5) operations.
Hence if min = minimum element in array, then change all elements to min may not be optimal.
The part you do not understand is to cater this situation, we know min may not be optimal as min-x maybe better, but how large is x? Well it is 4. The editorial is saying if we know x is at most 4, we can just simply brute force min, min-1...min-4 to see which one is the minimum without thinking too much.
Reasoning (Not proof!) for x <= 4
If x >= 5, then you have to use at least extra N type 3 (minus 5) operations on all elements which is definitely not worth.
Basically it is not a matter of the type of operation, it is because you need to use same operation on ALL elements, after you do that, the problem is not reduced, the relative difference between elements is still the same while you aim to make the relative difference to 0, you cost N operations for nothing.
In other words, if x >= 5, then x-5 must be a more optimal choice of goal, indeed x%5 must be the best goal.
(Below is TL;DR part: Version 2) Jump to the Last Section If You are Not Interested in the proof
In the process of writing the original solution, I suspect x <= 2 indeed, and I have tried to submit a code on HackerRank which only check minimum for f(min-x) where x <= 2, and it got ACed.
More formally, I claim
If 5> (z-min)%5 >= 3 and (z-min')%5==0, then F(min')< F(min)
where min'=min-x for x<=2, F(k) = min # of operation for element z to become k
(Beware the notation, I use F(), it is different meaning from f() in the question)
Here is the proof:
If (z-min)%5 = 1 or 2, then it needs at least (z-min)/5 + 1 operations, while (z-min')%5 == 0 needs (z-min')/5 = (z-min)/5 + 1 operation, means F(min') = F(min)
If(z-min)%5 == 3 or 4, then it needs at least (z-min)/5 + 2 operations, while (z-min')%5 == 0 needs (z-min')/5 = (z-min)/5 + 1 operation, means F(min') < F(min) (or F(min') = F(min)+1)
So we proof
If 5> (z-min)%5 >= 3 and (z-min')%5==0, then F(min')< F(min)
where min'=min-x
Now let's proof the range of x
As we assume (z-min)%5 >= 3 and (z-min')%5 == 0,
so (z-min')%5 = (z-min+x)%5 = ((z-min)%5 + x%5)%5 == 0
Now, if x >= 3, then (z-min)%5 can never be >= 3 in order to make ((z-min)%5 + x%5)%5 == 0
If x = 2, then (z-min)%5 can be 3; if x = 1 then (z-min)%5 can be 4, to meet both conditions: 5> (z-min)%5 >= 3 and (z-min')%5==0
Thus together we show
If 5> (z-min)%5 >= 3 and (z-min')%5==0, then F(min')< F(min)
where min'=min-x for x<=2
Note one can always generate array P, such that f(min') < f(min), as you can always repeat integer which can be improved by such method until it out number those integers cannot. This is because for elements that cannot be improved, they will always need exactly 1 more operations
eg: Let P = [2,2,2,10] f(min) = 0+3 = 3, f(min-2) = 3+2 = 5
Here 10 is the element which can be improved, while 2 cannot, so we can just add more 10 in the array. Each 2 will use 1 more operation to get to min' = min-2, while each 10 will save 1 operation to get min'. So we only have to add more 10 until it out number (compensate) the "waste" of 2:
P = [2,2,2,10,10,10,10,10], then f(min) = 0+15 = 15, f(min-2) = 3+10=13
or simply just
P = [2,10,10], f(min) = 6, f(min-2) = 5
(End of TL;DR part!)
EDITED
OMG THE TEST CASE ON HACKERRANK IS WEAK!
Story is when I arrive my office this morning, I keep thinking this problem a bit, and think that there maybe a problem in my code (which got ACed!)
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int T, n, a[10005], m = 1<<28;
int f(int m){
m = max(0, m);
int cnt = 0;
for(int i=0; i<n;i++){
cnt += (a[i]-m)/5 + (a[i]-m)%5/2 + (a[i]-m)%5%2;
}
return cnt;
}
int main() {
cin >> T;
while(T--){
m = 1<<28;
cin >> n;
for(int i=0; i<n;i++) cin >> a[i], m = min(m,a[i]);
cout << min(min(f(m), f(m-1)),f(m-2)) << endl;
}
return 0;
}
Can you see the problem?
The problem is m = max(0, m); !
It ensure that min-x must be at least 0, but wait, my proof above did not say anything about the range of min-x! It can be negative indeed!
Remember the original question is about "adding", so there is no maximum value of the goal; while we model the question to "subtracting", there is no minimum value of the goal as well (but I set it to 0!)
Try this test case with the code above:
1
3
0 3 3
It forces min-x = 0, so it gives 4 as output, but the answer should be 3
(If we use "adding" model, the goal should be 10, with +5 on a[0],a[2], +5 on a[0],a[1], +2 on a[1], a[2])
So everything finally got right (I think...) when I remove the line m = max(0, m);, it allows min-x to get negative and give 3 as a correct output, and of course the new code get ACed as well...

Find all possible combinations from 4 input numbers which can add up to 24

Actually, this question can be generalized as below:
Find all possible combinations from a given set of elements, which meets
a certain criteria.
So, any good algorithms?
There are only 16 possibilities (and one of those is to add together "none of them", which ain't gonna give you 24), so the old-fashioned "brute force" algorithm looks pretty good to me:
for (unsigned int choice = 1; choice < 16; ++choice) {
int sum = 0;
if (choice & 1) sum += elements[0];
if (choice & 2) sum += elements[1];
if (choice & 4) sum += elements[2];
if (choice & 8) sum += elements[3];
if (sum == 24) {
// we have a winner
}
}
In the completely general form of your problem, the only way to tell whether a combination meets "certain criteria" is to evaluate those criteria for every single combination. Given more information about the criteria, maybe you could work out some ways to avoid testing every combination and build an algorithm accordingly, but not without those details. So again, brute force is king.
There are two interesting explanations about the sum problem, both in Wikipedia and MathWorld.
In the case of the first question you asked, the first answer is good for a limited number of elements. You should realize that the reason Mr. Jessop used 16 as the boundary for his loop is because this is 2^4, where 4 is the number of elements in your set. If you had 100 elements, the loop limit would become 2^100 and your algorithm would literally take forever to finish.
In the case of a bounded sum, you should consider a depth first search, because when the sum of elements exceeds the sum you are looking for, you can prune your branch and backtrack.
In the case of the generic question, finding the subset of elements that satisfy certain criteria, this is known as the Knapsack problem, which is known to be NP-Complete. Given that, there is no algorithm that will solve it in less than exponential time.
Nevertheless, there are several heuristics that bring good results to the table, including (but not limited to) genetic algorithms (one I personally like, for I wrote a book on them) and dynamic programming. A simple search in Google will show many scientific papers that describe different solutions for this problem.
Find all possible combinations from a given set of elements, which
meets a certain criteria
If i understood you right, this code will helpful for you:
>>> from itertools import combinations as combi
>>> combi.__doc__
'combinations(iterable, r) --> combinations object\n\nReturn successive r-length
combinations of elements in the iterable.\n\ncombinations(range(4), 3) --> (0,1
,2), (0,1,3), (0,2,3), (1,2,3)'
>>> set = range(4)
>>> set
[0, 1, 2, 3]
>>> criteria = range(3)
>>> criteria
[0, 1, 2]
>>> for tuple in list(combi(set, len(criteria))):
... if cmp(list(tuple), criteria) == 0:
... print 'criteria exists in tuple: ', tuple
...
criteria exists in tuple: (0, 1, 2)
>>> list(combi(set, len(criteria)))
[(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
Generally for a problem as this you have to try all posebilities, the thing you should do have the code abort the building of combiantion if you know it will not satesfie the criteria (if you criteria is that you do not have more then two blue balls, then you have to abort calculation that has more then two). Backtracing
def perm(set,permutation):
if lenght(set) == lenght(permutation):
print permutation
else:
for element in set:
if permutation.add(element) == criteria:
perm(sett,permutation)
else:
permutation.pop() //remove the element added in the if
The set of input numbers matters, as you can tell as soon as you allow e.g. negative numbers, imaginary numbers, rational numbers etc in your start set. You could also restrict to e.g. all even numbers, all odd number inputs etc.
That means that it's hard to build something deductive. You need brute force, a.k.a. try every combination etc.
In this particular problem you could build an algoritm that recurses - e.g. find every combination of 3 Int ( 1,22) that add up to 23, then add 1, every combination that add to 22 and add 2 etc. Which can again be broken into every combination of 2 that add up to 21 etc. You need to decide if you can count same number twice.
Once you have that you have a recursive function to call -
combinations( 24 , 4 ) = combinations( 23, 3 ) + combinations( 22, 3 ) + ... combinations( 4, 3 );
combinations( 23 , 3 ) = combinations( 22, 2 ) + ... combinations( 3, 2 );
etc
This works well except you have to be careful around repeating numbers in the recursion.
private int[][] work()
{
const int target = 24;
List<int[]> combos = new List<int[]>();
for(int i = 0; i < 9; i++)
for(int x = 0; x < 9; x++)
for(int y = 0; y < 9; y++)
for (int z = 0; z < 9; z++)
{
int res = x + y + z + i;
if (res == target)
{
combos.Add(new int[] { x, y, z, i });
}
}
return combos.ToArray();
}
It works instantly, but there probably are better methods rather than 'guess and check'. All I am doing is looping through every possibility, adding them all together, and seeing if it comes out to the target value.
If i understand your question correctly, what you are asking for is called "Permutations" or the number (N) of possible ways to arrange (X) numbers taken from a set of (Y) numbers.
N = Y! / (Y - X)!
I don't know if this will help, but this is a solution I came up with for an assignment on permutations.
You have an input of : 123 (string) using the substr functions
1) put each number of the input into an array
array[N1,N2,N3,...]
2)Create a swap function
function swap(Number A, Number B)
{
temp = Number B
Number B = Number A
Number A = temp
}
3)This algorithm uses the swap function to move the numbers around until all permutations are done.
original_string= '123'
temp_string=''
While( temp_string != original_string)
{
swap(array element[i], array element[i+1])
if (i == 1)
i == 0
temp_string = array.toString
i++
}
Hopefully you can follow my pseudo code, but this works at least for 3 digit permutations
(n X n )
built up a square matrix of nxn
and print all together its corresponding crossed values
e.g.
1 2 3 4
1 11 12 13 14
2 .. .. .. ..
3 ..
4 .. ..

Generate Random(a, b) making calls to Random(0, 1)

There is known Random(0,1) function, it is a uniformed random function, which means, it will give 0 or 1, with probability 50%. Implement Random(a, b) that only makes calls to Random(0,1)
What I though so far is, put the range a-b in a 0 based array, then I have index 0, 1, 2...b-a.
then call the RANDOM(0,1) b-a times, sum the results as generated idx. and return the element.
However since there is no answer in the book, I don't know if this way is correct or the best. How to prove that the probability of returning each element is exactly same and is 1/(b-a+1) ?
And what is the right/better way to do this?
If your RANDOM(0, 1) returns either 0 or 1, each with probability 0.5 then you can generate bits until you have enough to represent the number (b-a+1) in binary. This gives you a random number in a slightly too large range: you can test and repeat if it fails. Something like this (in Python).
def rand_pow2(bit_count):
"""Return a random number with the given number of bits."""
result = 0
for i in xrange(bit_count):
result = 2 * result + RANDOM(0, 1)
return result
def random_range(a, b):
"""Return a random integer in the closed interval [a, b]."""
bit_count = math.ceil(math.log2(b - a + 1))
while True:
r = rand_pow2(bit_count)
if a + r <= b:
return a + r
When you sum random numbers, the result is not longer evenly distributed - it looks like a Gaussian function. Look up "law of large numbers" or read any probability book / article. Just like flipping coins 100 times is highly highly unlikely to give 100 heads. It's likely to give close to 50 heads and 50 tails.
Your inclination to put the range from 0 to a-b first is correct. However, you cannot do it as you stated. This question asks exactly how to do that, and the answer utilizes unique factorization. Write m=a-b in base 2, keeping track of the largest needed exponent, say e. Then, find the biggest multiple of m that is smaller than 2^e, call it k. Finally, generate e numbers with RANDOM(0,1), take them as the base 2 expansion of some number x, if x < k*m, return x, otherwise try again. The program looks something like this (simple case when m<2^2):
int RANDOM(0,m) {
// find largest power of n needed to write m in base 2
int e=0;
while (m > 2^e) {
++e;
}
// find largest multiple of m less than 2^e
int k=1;
while (k*m < 2^2) {
++k
}
--k; // we went one too far
while (1) {
// generate a random number in base 2
int x = 0;
for (int i=0; i<e; ++i) {
x = x*2 + RANDOM(0,1);
}
// if x isn't too large, return it x modulo m
if (x < m*k)
return (x % m);
}
}
Now you can simply add a to the result to get uniformly distributed numbers between a and b.
Divide and conquer could help us in generating a random number in range [a,b] using random(0,1). The idea is
if a is equal to b, then random number is a
Find mid of the range [a,b]
Generate random(0,1)
If above is 0, return a random number in range [a,mid] using recursion
else return a random number in range [mid+1, b] using recursion
The working 'C' code is as follows.
int random(int a, int b)
{
if(a == b)
return a;
int c = RANDOM(0,1); // Returns 0 or 1 with probability 0.5
int mid = a + (b-a)/2;
if(c == 0)
return random(a, mid);
else
return random(mid + 1, b);
}
If you have a RNG that returns {0, 1} with equal probability, you can easily create a RNG that returns numbers {0, 2^n} with equal probability.
To do this you just use your original RNG n times and get a binary number like 0010110111. Each of the numbers are (from 0 to 2^n) are equally likely.
Now it is easy to get a RNG from a to b, where b - a = 2^n. You just create a previous RNG and add a to it.
Now the last question is what should you do if b-a is not 2^n?
Good thing that you have to do almost nothing. Relying on rejection sampling technique. It tells you that if you have a big set and have a RNG over that set and need to select an element from a subset of this set, you can just keep selecting an element from a bigger set and discarding them till they exist in your subset.
So all you do, is find b-a and find the first n such that b-a <= 2^n. Then using rejection sampling till you picked an element smaller b-a. Than you just add a.

Resources