Given the API rand7() that generates a uniform random integer in the range [1, 7], write a function rand10() that generates a uniform random integer in the range [1, 10]. You can only call the API rand7(), and you shouldn't call any other API. Please do not use a language's built-in random API.
Each test case will have one internal argument n, the number of times that your implemented function rand10() will be called while testing. Note that this is not an argument passed to rand10().
Example 1:
Input: n = 1 Output: [2]
Example 2:
Input: n = 2 Output: [2,8]
Example 3:
Input: n = 3 Output: [3,8,10]
Constraints:
1 <= n <= 105Follow up:
rand7() function?rand7()?When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We need to simulate rolling a ten-sided die using only a seven-sided die. The brute force method essentially keeps re-rolling the seven-sided die until we get a result that directly corresponds to a number between one and ten.
Here's how the algorithm would work step-by-step:
def rand10_brute_force(rand7):
while True:
roll_result = rand7()
# Discard values outside the range 1-7
if roll_result <= 7:
# Map the 7 possible outcomes to 1-7 directly
return roll_resultWe need to simulate a 10-sided die using only a 7-sided die. The key idea is to combine multiple rolls of the 7-sided die to create a larger range of possibilities that can then be mapped onto the numbers 1 to 10 efficiently, discarding results that don't fit.
Here's how the algorithm would work step-by-step:
def rand7():
# Assume this function exists and returns a random integer in the range 1 to 7 (inclusive).
pass
def rand10():
while True:
first_roll = rand7()
second_roll = rand7()
# Effectively create a uniform distribution from 1 to 49
combined_result = (first_roll - 1) * 7 + second_roll
# If the result is greater than 40, we reroll because it's biased.
if combined_result <= 40:
# Map the range 1-40 to 1-10, since 40 is divisible by 10.
return (combined_result - 1) % 10 + 1| Case | How to Handle |
|---|---|
| rand7() returns values clustered at one end of its range (e.g., mostly 1s) | The solution should still produce a uniform distribution for rand10() regardless of non-uniformity in rand7(). |
| rand7() has a slight bias towards certain numbers | The rejection sampling method in rand10() is designed to minimize the impact of any slight biases in rand7(). |
| Integer overflow when combining results from multiple rand7() calls. | Carefully choose combinations and modulo operations to avoid exceeding integer limits. |
| The theoretical maximum number of calls to rand7() before a valid rand10() value is generated is very high. | The algorithm should still terminate eventually, but consider logging or monitoring if the average number of calls is significantly higher than expected. |
| rand7() returns 0 (although this is outside its specified range, it's important to consider unexpected behavior). | Handle this case by treating 0 as an invalid return and re-calling rand7(). |
| Stack overflow if using recursion excessively in case of extremely biased rand7() function. | Convert the recursive approach to an iterative one, if implemented using recursion. |
| The generated number has a high probability of being a certain value. | The solution should produce numbers between 1 and 10 with equal probability, even when called many times. |
| The number of calls to rand7() impacts performance. | Minimize the average number of calls to rand7() required to generate a single rand10() value by efficiently combining its outputs. |