명일방주 픽업을 위한 평균 가챠횟수 1편(6성 획득)
1. 기본 가정
모바일 게임 명일방주 헤드헌팅 시스템은 기본적으로 다음과 같다.
1. 3성 등장 확률 40%, 4성 등장 확률 50% 5성 등장 확률 8%, 6성 등장 확률 2%
2. 가챠 시도 횟수 1회부터 50회까지는 6성 등장 확률이 2%이고 51회부터는 6성 등장 확률이 2%p씩 증가하여 99회에는 확정적으로 6성을 획득함(100%)
3. 가챠 시도 중 6성을 획득하는 순간 2.의 확률 버프는 처음부터 초기화됨
4. 처음부터 10회 이내에 5성 이상 캐릭터를 확정적으로 획득함
1회부터 9회까지 5성 이상을 획득하지 못했다면 10회때 98%확률로 5성을 획득하고 2%확률로 6성을 획득함
이 보너스는 가챠에서 오직 1번만 적용됨
여러가지 경우에 따라 평균적인 가챠횟수를 알아보자
2. 상황
100만명의 명일방주 유저가 동시에 특정 헤드헌팅을 수행한다고 가정하자
모든 유저의 확률 버프는 0인 상태라고 가정하고
목표로 하는 캐릭터를 획득할때까지 각 유저가 시도한 가챠횟수를 수집하여 평균을 내서 최종적으로 특정 상황에 대한 평균적인 가챠 횟수를 구해본다.
3. 임의의 6성을 획득하기 위해 돌려야하는 평균적인 가챠 횟수는?
import random
pickup_list = ['6성','5성','4성','3성']
weight_list = [0.02,0.08,0.50,0.40]
random module을 부르고 픽업 확률에 따라 리스트를 만든다
def try_six(pickup_list,weight_list):
try_num = 1
bonus = False
while 1:
if bonus == False:
#10회 이내 보너스
if try_num < 10:
a = random.choices(pickup_list,weights=weight_list)
else:
a = random.choices(['6성','5성'],weights=[0.02,0.98])
if a == ['5성']:
bonus = True
elif a== ['6성']:
break
else: #bonus 없어지고
#50회 이내 가챠 확률
if try_num <= 50:
a = random.choices(pickup_list,weights=weight_list)
if a == ["6성"]:
break
else: #51회 이후 가챠 확률
six_prob = 0.02*(try_num-49)
pickup_list = ['6성','기타']
a = random.choices(pickup_list,weights=[six_prob,1-six_prob])
if a == ["6성"]:
break
try_num += 1
return try_num
try_num = 1로 시도횟수 초기화
bonus=False로 bonus에 대한 지시변수 초기화
while 1:로 6성이 나올때까지 반복적으로 random sampling을 함
def try_six(pickup_list,weight_list):
try_num = 1
bonus = False
while 1:
if bonus == False:
#10회 이내 보너스
if try_num < 10:
a = random.choices(pickup_list,weights=weight_list)
else:
a = random.choices(['6성','5성'],weights=[0.02,0.98])
#5성, 6성 검사
if a == ['5성']:
bonus = True
elif a== ['6성']:
break
처음엔 bonus가 안터진 상태니까 bonus==False인 상태에서 while문이 수행되는데
try_num<10으로 10회 미만의 시도횟수에선 기본 확률을 적용하여 가챠를 수행
가챠를 수행하고 나서는 5성인지 6성인지를 검사함
6성이면 목표를 수행했으니 반복문 탈출하고 try_num을 return하는데
5성이면 bonus가 터졌으니까 bonus=True로 변경함
try_num=10일때까지 bonus=False이면 6성은 2%, 5성은 98% 확률로 조정함
else:
if try_num <= 50:
a = random.choices(pickup_list,weights=weight_list)
if a == ["6성"]:
break
else:
six_prob = 0.02*(try_num-49)
pickup_list = ['6성','기타']
a = random.choices(pickup_list,weights=[six_prob,1-six_prob])
if a == ["6성"]:
break
try_num += 1
return try_num
다음으로 bonus가 터진 경우에 대해서는 try_num이 50회까지는 기본 확률을 적용하여 pickup을 수행
6성이 나오면 그 자리에서 반복문을 탈출하고 try_num을 return함
51회부터는 6성 확률이 0.02씩 상승하여 조정이 됨
51회는 0.04 , 52회는 0.06,... 일반항으로 0.02(try_num-49)로 구할 수 있음
픽업 리스트를 6성과 기타의 경우로 조정하고 픽업 수행
6성이 나오면 그대로 반복문 탈출하고 try_num return함
total_man = 1000000
sum_of_try = 0
for _ in range(total_man):
try_num = try_six(pickup_list,weight_list)
sum_of_try = sum_of_try + try_num
expect = sum_of_try/total_man
print(expect)
100만명의 사람이 픽업을 동시에 수행하여 시도한 try_num을 구하여 sum_of_try에 더해간다
마지막에 sum_of_try에 100만으로 나눠주면 평균적인 가챠횟수 구할 수 있음
34.53,34.56,34.57,....이 나와서 6성을 획득하는데 평균 약 34.5회 가챠를 수행한다.
'알고리즘 > 알고리즘 일반' 카테고리의 다른 글
명일방주 픽업을 위한 평균 가챠횟수 4편(일반 헤드헌팅) (0) | 2021.11.09 |
---|---|
명일방주 픽업을 위한 평균 가챠횟수 3편(한정 헤드헌팅) (0) | 2021.11.09 |
명일방주 픽업을 위한 평균 가챠횟수 2편(위기협약) (0) | 2021.11.09 |
deque를 사용해야할때는? (0) | 2021.11.08 |
문자열 필수 replace 활용 (0) | 2021.11.07 |