@@ -11,9 +11,36 @@ def zero_one_random():
1111 return random .randrange (2 )
1212
1313
14+ def uniform_random_wrong (lower_bound : int , upper_bound : int ) -> int :
15+ # How about a binary search where hi vs lo is chosen randomly?
16+ # This doesn't work, because numbers towards the middle of the array
17+ # have a higher chance of being chosen than ones closer to the edge (there)
18+ # are more paths leading to them.
19+ while lower_bound <= upper_bound :
20+ mid = (lower_bound + upper_bound ) // 2
21+ if zero_one_random ():
22+ lower_bound = mid + 1
23+ else :
24+ upper_bound = mid - 1
25+ return lower_bound
26+
27+
1428def uniform_random (lower_bound : int , upper_bound : int ) -> int :
15- # TODO - you fill in here.
16- return 0
29+ """
30+ We want to randomly generate a value in [lo, hi]. Note that if we can generate a value
31+ from [0, hi-lo], we can just add it to lo, which will range from lo (if the number is 0)
32+ to hi (if the number is hi-lo, since hi-lo+lo = hi). To generate a number from 0 to hi-lo,
33+ this function uses a dumb strategy of determining how many bits are in hi-lo, then selecting
34+ a value for each of those bits via zero_one_random(). If we overshoot hi-lo, we just retry.
35+ This might not work (e.g. suppose hi = 2^30 + c and lo = 1, so hi-lo is 30 bits long; we have
36+ potentially 1073741824 30-bit values that exceed 2^30, so we could be retrying for a long time.
37+ """
38+ k = upper_bound - lower_bound
39+ bits = len (bin (k )[2 :])
40+ val = k + 1
41+ while val > k :
42+ val = int ('' .join ([str (zero_one_random ()) for i in range (bits )]), 2 )
43+ return val + lower_bound
1744
1845
1946@enable_executor_hook
@@ -33,7 +60,10 @@ def uniform_random_runner(executor, lower_bound, upper_bound):
3360
3461
3562if __name__ == '__main__' :
63+ # print(uniform_random(0, 10))
64+ # """
3665 exit (
3766 generic_test .generic_test_main ('uniform_random_number.py' ,
3867 'uniform_random_number.tsv' ,
3968 uniform_random_wrapper ))
69+ # """
0 commit comments