The gifter sends out a bunch of red packets with a random amount of money in each. The person who gets the least amount of money wins the game. Think about Sai Weng lost his horse -- what seems to be unfortunate is a blessing.
The total amount of money is 10 yuan. 30 people are expected to participate.
I opened a red packet -- 0.67 yuan. Not a bad one, only if the luckiest draw wins the game.
...
With Code Vein out of the question, when should I grab the red packet?
Take a guess
According to an employee in Wechat (in Chinese), the red packets' values are determined at the time they are opened, rather than the time they are sent out. And the value is chosen from a uniform distribution between 0.00 yuan and 2 times the average of the remaining red packets. For example, there are 10 packets and 3 yuan left, then the value of next red packet X∼U[0.00,3.00/10×2]. The result is clipped to 0.01 yuan minimum and rounded to the nearest 0.01 yuan.
Assume it is true, in the beginning the remaining amount is definite and certain, so we have a uniform distribution. After n draws, the uncertainty of the remaining amount grows. And since the amount of the red packet depends on this remaining money, it will get more uncertainty as well.
Therefore, if we want to win, and do not know how much is taken, we should enter as late as possible.
I will show you how I approached this problem, with some code.
The Math
Flop
For simplicity, let the lower bound to be 0, and let there be no rounding to the nearest 0.01 yuan, nor having a minimum of 0.01 yuan.
Let there be n red packets with a total value of y. The money of each draw is X1,X2,…,Xn.
I decided to go to ChatGPT for help in plotting, and it was more than helpful -- it could even fix errors using the error message.
Anyways, here is the graph of the PDF function:
Turn
Spare me with a Monte-Carlo to get the histogram of the third red packet...
import numpy as np
import matplotlib.pyplot as plt
# Parametersn =30y =10num_samples =1000000current =3partial_sums = np.zeros(num_samples)samples =[]for i inrange(current):if(i == n -1): samples.append(y - partial_sums)else: samples.append(np.random.uniform(0,2*(y - partial_sums)/(n-i))) partial_sums += samples[i]# Plot histogramplt.hist(samples[current -1], bins=1000, density=True, alpha=0.7, label=f'Approximated PDF of red packet #{current}')plt.xlabel(f'$x_{{{current}}}$')plt.ylabel('Density')plt.title(f'Histogram of $X_{{{current}}}$')plt.legend()plt.grid(True)plt.show()
To do it with algebra, we can look at the self-similarity of the problem. Imagine we have (n−1) red packets with a sum of (y−x1) yuan. The second red packet has a distribution of:
And with the Monte Carlo method, we can also take a look at the last red packet:
The histogram looks pretty much like the right half of a normal function. But it was rejected, and the p-value is zero in double precision.
Finding Estimates
Since it is hard to calculate the exact function, as the pieces increase one fold with each draw, let us assume the right part is a normal distribution, and to see if it reaches some kind of a fixed point. If it is I am more confident to say it is.
First the constant part on the left, solving for x4, we have:
Since σ=n2π, the mean of the half-norm is μ=n2. It agrees with the actual value when disregarding the error terms. So it is a possibility. Since it is currently out of my reach to figure out the plateau part, I believe Monte Carlo is the best way to go for now.
Running away from Difficulties
Using Monte Carlo it is easy to figure out the chance of winning for each people drawing.
import numpy as np
import matplotlib.pyplot as plt
# Parametersn =30Y =10num_samples =1000000current = n
partial_sums = np.zeros(num_samples)samples = np.zeros((n, num_samples))for i inrange(current):if(i == n -1): samples[i,:]= Y - partial_sums
else: samples[i,:]= np.random.uniform(0,2*(Y - partial_sums)/(n-i)) partial_sums += samples[i,:]min_samples = np.argmin(samples, axis=0)# Plot histogram# use (n+1) bins so [0, n] is filledplt.hist(min_samples, bins=np.arange(n+2), density=True, histtype='stepfilled', rwidth=1, alpha=0.7)plt.xlabel(f'$n$-th Draw')plt.ylabel('Probability')plt.title(f'Chance of Being The Unluckiest, n={n}')# plt.legend()plt.grid(True)plt.show()
Here is the graph:
We can see the last person to draw has a better chance of winning, it has an advantage at around 1/3.
Changing n to 100, we still see a smaller advantage.
What I found surprising is the luckiest draw. The last draws have a huge advantage, then the first few, the middle ones have the least chance of being the luckiest:
If we take into consideration rounding up to 0.01yuan if the random number is less than it, or to the closest 0.01 yuan, we need to take care of breaking ties:
for i inrange(current):if(i == n -1): samples[i,:]=Y- partial_sums
else: samples[i,:]= np.random.uniform(0,2*(Y- partial_sums)/(n-i)) samples[i,:]= np.clip(samples[i,:],0.01, np.inf) samples[i,:]= np.round(samples[i,:]/0.01)*0.01 partial_sums += samples[i,:]# Since argmin returns the first occurrence, the first draw will be highly favored
# when there are multiple 0.01 packets,# so we need a fair way of breaking ties:# If the red packet amount equals the least amount, assign a 1, otherwise a 0# so if we add a random [0,1) number to it, we can randomly break ties when there are multiple minimums
min_samples = np.argmax(np.random.random((n, num_samples))+(samples == np.min(samples, axis=0)), axis=0)
But the graph is the same:
That is about it.
Conclusion
If you are aiming for the unluckiest, wait until the last minute if you can. You can get a little more value.
You may completely whiff it because QQ and Wechat don't tell you how many red packets are gone, though!