Probability Simulation & Optimal Strategy for Users
11/26/2023
Portfolio
A. Simulated a probability-based item that follows the sequence below in Python
- Participate in the online store with participation rights (1 for 9,000 KRW).
- When a total of 50 people gather, each person is assigned a number, and the draw begins,
- Out of the 50 people, 10 people win a “reward” & earn “1 point”.
- Out of the 50 people, the remaining 40 people receive only “1 point” as they did not win.
- The 40 people who didn’t win can spend 500 KRW to make an additional selection.
5-1) Choose one from the remaining 49 options, excluding your own number, and if the selected number matches the winning number, receive an additional 1 point (total of 2 points).
5-2) If successful in 5-1), choose one from the remaining 48 options, excluding your own number and the previous matching number, and if the selected number matches the winning number, receive an additional 1 point (total of 3 points).
…
5-10) If successful in 5-9), choose one from the remaining 40 options, excluding your own number and the previous matching numbers, and if the selected number matches the winning number, receive an additional 1 point (total of 11 points). - If you fail at any stage from 5-1) to 5-9), you cannot proceed to the next stage.
- Participants can collect points obtained from unsuccessful attempts, and they can use these points to purchase items at the bottom of the page (1 / 2 / 5 / 10 / 30 points).
import random
import seaborn as sns
import matplotlib.pyplot as plt
#Selling price
cash = 9000
#In-game value of the rewards
product_price = {"winning":250000000, "1":45000000, "2":100000000, "5":300000000, "10":650000000, "30":20000000000}
total_games = int(1e4) # Total number of games
total_people = int(1e3) # Total number of users
point_list = [0 for _ in range(total_people)] # Store points acquired by users
paid_list = [0 for _ in range(total_people)] # Store the amount spent by users
price_list = [0 for _ in range(total_people)] # Store the value of products acquired by users
result_list = [[0, 0] for _ in range(total_people)] # Store the game results of users
for game in range(total_games):
total_game_numbers = list(range(0, 49))
npc_choice = random.sample(total_game_numbers, 10) # Selected winning numbers in the game
for user in range(total_people):
user_cnt = 0
user_game_numbers = total_game_numbers.copy()
# Adjusting the probability of continuing the game based on the amount of spending
# Most users make a purchase at least once, and the number of users making additional purchases after one round decreases significantly.
# Then, there is a gradual decrease in willingness to purchase, and in the high-spending user segment, there is very little resistance to additional spending.
# This has been implemented with approximate probabilities.
if (paid_list[user] >= 100000):
limit_prob = 0.90
elif (paid_list[user] >= 50000) and (paid_list[user] < 100000):
limit_prob = 0.95
elif (paid_list[user] >= 9000) and (paid_list[user] < 50000):
limit_prob = 0.95
else:
limit_prob = 0.3
if random.random() >= limit_prob: # Randomly decide whether to play the game
paid_list[user] += 9000 # Cost based on the user's first choice
user_choice = random.sample(user_game_numbers, 1)[0] # User's first choice
if user_choice in npc_choice: # Check if the user won
price_list[user] += product_price["winning"] # Receive the Rewards if the user wins
point_list[user] += 1 # Earn 1 point if the user wins
result_list[user][0] += 1 # Record the winning result
continue
else:
point_list[user] += 1 # Earn 1 point even if not winning
user_game_numbers.remove(user_choice)
if random.random() > limit_prob: # Case 1: Continue the game
stop_or_go = 1
else: # Case 2: Discontinue the game
stop_or_go = 0
while stop_or_go == 1:
paid_list[user] += 500 # Cost for additional games
user_cnt += 1
if user_cnt == 11:
break
user_choice = random.sample(user_game_numbers, 1)[0] # User's choice
if user_choice in npc_choice:
point_list[user] += 1 # Earn points
result_list[user][1] += 1 # Increase the number of correct guesses
if random.random() > limit_prob: # Case 1: Winning the game and continuing
stop_or_go = 1
else: # Case 2: Winning the game and not continuing
stop_or_go = 0
else:
stop_or_go = 0 # When losing the game, cannot draw again
else:
continue
# Exchange for items with pt.s
product_list = [30, 10, 5, 2, 1]
for user in range(total_people):
left_point = point_list[user]
for product in product_list:
products = left_point // product
left_point = left_point % product
price_list[user] += products * product_price[str(product)]
Final item value obtained by each user
sns.histplot(price_list, kde=True)
plt.show()
Final Spending Amounts by each user
sns.histplot(paid_list, kde=True)
plt.show()
price_list[user] / paid_list[user]. # The in-game currency value per 1 KRW
16006.339144215532
Utilized in the actual probability item configuration
By changing the item value, base purchase amount (9000 KRW), and additional selection purchase amount (500 KRW), I found a value for the in-game currency that is almost identical to what was previously sold. The probability item scheme itself is simple, but calculating the expected value is relatively complex, so I found Python implementation to be very helpful.
B. Examined user’s optimal strategies
Strategy 1: Participate in all games and do not make additional selections.
total_games = int(1e2) # Total number of games
total_people = int(1e4) # Total number of users
point_list = [0 for _ in range(total_people)] # Store points acquired by users
paid_list = [0 for _ in range(total_people)] # Store the amount spent by users
price_list = [0 for _ in range(total_people)] # Store the value of products acquired by users
result_list = [[0, 0] for _ in range(total_people)] # Store the game results of users
for game in range(total_games):
total_game_numbers = list(range(0, 49))
npc_choice = random.sample(total_game_numbers, 10) # Selected winning numbers in the game
for user in range(total_people):
user_cnt = 0
user_game_numbers = total_game_numbers.copy()
# the probability of continuing the game
limit_prob = 0
if random.random() >= limit_prob: # Randomly decide whether to play the game
paid_list[user] += 9000 # Cost based on the user's first choice
user_choice = random.sample(user_game_numbers, 1)[0] # User's first choice
if user_choice in npc_choice: # Check if the user won
price_list[user] += product_price["winning"] # Receive the Rewards if the user wins
point_list[user] += 1 # Earn 1 point if the user wins
result_list[user][0] += 1 # Record the winning result
continue
else:
point_list[user] += 1 # Earn 1 point even if not winning
user_game_numbers.remove(user_choice)
else:
continue
product_list = [30, 10, 5, 2, 1]
for user in range(total_people):
left_point = point_list[user]
for product in product_list:
products = left_point // product
left_point = left_point % product
price_list[user] += products * product_price[str(product)]
sns.histplot(price_list, kde=True)
plt.show()
price_list[user] / paid_list[user] # The in-game currency value per 1 KRW
12388.888888888889
Less efficient than the overall average.
The overall in-game currency value per 1 KRW was 16,006, but Strategy 1 is lower at 12,388.
*I ran overall simulation considering high-spending users (1,000 people, 10,000 tries each). However, for personal strategies, I assumed that most are low/medium spenders (1,000 people, 100 tries each). This makes direct comparison of overall efficiency difficult, requiring comparison by each strategy’s efficiency.
*I ran overall simulation considering high-spending users (1,000 people, 10,000 tries each). However, for personal strategies, I assumed that most are low/medium spenders (1,000 people, 100 tries each). This makes direct comparison of overall efficiency difficult, requiring comparison by each strategy’s efficiency.
Strategy 2: Participate in all games and make an additional selection only once.
total_games = int(1e2) # Total number of games
total_people = int(1e4) # Total number of users
point_list = [0 for _ in range(total_people)] # Store points acquired by users
paid_list = [0 for _ in range(total_people)] # Store the amount spent by users
price_list = [0 for _ in range(total_people)] # Store the value of products acquired by users
result_list = [[0, 0] for _ in range(total_people)] # Store the game results of users
for game in range(total_games):
total_game_numbers = list(range(0, 49))
npc_choice = random.sample(total_game_numbers, 10) # Selected winning numbers in the game
for user in range(total_people):
user_cnt = 0
user_game_numbers = total_game_numbers.copy()
# the probability of continuing the game
limit_prob = 0
if random.random() >= limit_prob: # Randomly decide whether to play the game
paid_list[user] += 9000 # Cost based on the user's first choice
user_choice = random.sample(user_game_numbers, 1)[0] # User's first choice
if user_choice in npc_choice: # Check if the user won
price_list[user] += product_price["winning"] # Receive the Rewards if the user wins
point_list[user] += 1 # Earn 1 point if the user wins
result_list[user][0] += 1 # Record the winning result
continue
else:
point_list[user] += 1 # Earn 1 point even if not winning
user_game_numbers.remove(user_choice)
stop_or_go = 1
while stop_or_go == 1:
paid_list[user] += 500 # Cost for additional games
user_choice = random.sample(user_game_numbers, 1)[0] # User's Choice
user_cnt += 1
limit_game = 2 # Limit Game
if user_cnt == limit_game:
break
if user_choice in npc_choice:
point_list[user] += 1 # Earn points
result_list[user][1] += 1 # Increase the number of correct guesses
if random.random() > limit_prob: # Case 1: Winning the game and continuing
stop_or_go = 1
else: # Case 2: Winning the game and not continuing
stop_or_go = 0
else:
stop_or_go = 0 # When losing the game, cannot draw again
else:
continue
product_list = [30, 10, 5, 2, 1]
for user in range(total_people):
left_point = point_list[user]
for product in product_list:
products = left_point // product
left_point = left_point % product
price_list[user] += products * product_price[str(product)]
sns.histplot(price_list, kde=True)
plt.show()
price_list[user] / paid_list[user] # The in-game currency value per 1 KRW
13157.894736842105
Better than Strategy 1.
Strategy 2(efficiency of 13,157) was better than Strategy 1, which had an efficiency of 12,388.
Strategy 3: Participate in all games and make an additional selection only Twice.
total_games = int(1e2) # Total number of games
total_people = int(1e4) # Total number of users
point_list = [0 for _ in range(total_people)] # Store points acquired by users
paid_list = [0 for _ in range(total_people)] # Store the amount spent by users
price_list = [0 for _ in range(total_people)] # Store the value of products acquired by users
result_list = [[0, 0] for _ in range(total_people)] # Store the game results of users
for game in range(total_games):
total_game_numbers = list(range(0, 49))
npc_choice = random.sample(total_game_numbers, 10) # Selected winning numbers in the game
for user in range(total_people):
user_cnt = 0
user_game_numbers = total_game_numbers.copy()
# the probability of continuing the game
limit_prob = 0
if random.random() >= limit_prob: # Randomly decide whether to play the game
paid_list[user] += 9000 # Cost based on the user's first choice
user_choice = random.sample(user_game_numbers, 1)[0] # User's first choice
if user_choice in npc_choice: # Check if the user won
price_list[user] += product_price["winning"] # Receive the Rewards if the user wins
point_list[user] += 1 # Earn 1 point if the user wins
result_list[user][0] += 1 # Record the winning result
continue
else:
point_list[user] += 1 # Earn 1 point even if not winning
user_game_numbers.remove(user_choice)
stop_or_go = 1
while stop_or_go == 1:
paid_list[user] += 500 # Cost for additional games
user_choice = random.sample(user_game_numbers, 1)[0] # User's Choice
user_cnt += 1
limit_game = 3 # Limit Game
if user_cnt == limit_game:
break
if user_choice in npc_choice:
point_list[user] += 1 # Earn points
result_list[user][1] += 1 # Increase the number of correct guesses
if random.random() > limit_prob: # Case 1: Winning the game and continuing
stop_or_go = 1
else: # Case 2: Winning the game and not continuing
stop_or_go = 0
else:
stop_or_go = 0 # When losing the game, cannot draw again
else:
continue
product_list = [30, 10, 5, 2, 1]
for user in range(total_people):
left_point = point_list[user]
for product in product_list:
products = left_point // product
left_point = left_point % product
price_list[user] += products * product_price[str(product)]
sns.histplot(price_list, kde=True)
plt.show()
price_list[user] / paid_list[user] # The in-game currency value per 1 KRW
14013.749338974088
Better than Strategy 1/2.
Strategy 3(efficiency of 14,013) was better than Strategy 1(efficiency of 12,388) and Strategy 2(efficiency of 13,157).
Strategy 4: Participate in all games and make additional choices as much as possible.
total_games = int(1e2) # Total number of games
total_people = int(1e4) # Total number of users
point_list = [0 for _ in range(total_people)] # Store points acquired by users
paid_list = [0 for _ in range(total_people)] # Store the amount spent by users
price_list = [0 for _ in range(total_people)] # Store the value of products acquired by users
result_list = [[0, 0] for _ in range(total_people)] # Store the game results of users
for game in range(total_games):
total_game_numbers = list(range(0, 49))
npc_choice = random.sample(total_game_numbers, 10) # Selected winning numbers in the game
for user in range(total_people):
user_cnt = 0
user_game_numbers = total_game_numbers.copy()
# the probability of continuing the game
limit_prob = 0
if random.random() >= limit_prob: # Randomly decide whether to play the game
paid_list[user] += 9000 # Cost based on the user's first choice
user_choice = random.sample(user_game_numbers, 1)[0] # User's first choice
if user_choice in npc_choice: # Check if the user won
price_list[user] += product_price["winning"] # Receive the Rewards if the user wins
point_list[user] += 1 # Earn 1 point if the user wins
result_list[user][0] += 1 # Record the winning result
continue
else:
point_list[user] += 1 # Earn 1 point even if not winning
user_game_numbers.remove(user_choice)
stop_or_go = 1
while stop_or_go == 1:
paid_list[user] += 500 # Cost for additional games
user_choice = random.sample(user_game_numbers, 1)[0] # User's Choice
user_cnt += 1
limit_game = 3 # Limit Game
if user_cnt == limit_game:
break
if user_choice in npc_choice:
point_list[user] += 1 # Earn points
result_list[user][1] += 1 # Increase the number of correct guesses
if random.random() > limit_prob: # Case 1: Winning the game and continuing
stop_or_go = 1
else: # Case 2: Winning the game and not continuing
stop_or_go = 0
else:
stop_or_go = 0 # When losing the game, cannot draw again
else:
continue
product_list = [30, 10, 5, 2, 1]
for user in range(total_people):
left_point = point_list[user]
for product in product_list:
products = left_point // product
left_point = left_point % product
price_list[user] += products * product_price[str(product)]
sns.histplot(price_list, kde=True)
plt.show()
price_list[user] / paid_list[user] # The in-game currency value per 1 KRW
14062.5
Better than Strategy 1/2. Similar to Strategy 3.
Strategy 4(efficiency of 14,062) was better than Strategy 1(efficiency of 12,388), Strategy 2(efficiency of 13,157). But its efficiency was similar to Strategy 3(efficiency of 14,013).
Conclusion
It was difficult to clearly state how many additional choices would be advantageous, but it can be said that neither avoiding extra choices altogether like in Strategy 1 nor making just one additional choice like in Strategy 2 is an efficient option.