참고자료: 2021-06-final

Author

최규빈

Published

June 6, 2021

오픈 북, 2시간, 문제미리공개

2021년 파이썬입문 기말고사 (풀이포함)

# 1. (20점)

N사에서 게임유저들에게 여름방학 기념이벤트로 진명왕의 집판검이라는 이름의 아이템을 선물했다고 하자. 진명왕의 집판검은 총 5회에 걸쳐서 강화(upgrade)될 수 있데 강화의 성공확률은 10%라고 하자. 강화가 5번성공하면 더 이상 강화가 진행되지 않는다고 하자. (따라서 더 이상 강화시도를 하지 않아도 무방하다) 아래는 이 아이템에 강화를 진행하였을때 각 강화상태를 설명한 예시이다.

시도횟수 강화성공여부 강화상태 비고
1 강화실패 +0 \(\to\) +0 강화실패로 인하여 강화상태 변화없음
2 강화성공 +0 \(\to\) +1 강화성공으로 인한 강화상태 변화
3 강화실패 +1 \(\to\) +1 강화실패로 인하여 강화상태 변화없음
4 강화성공 +1 \(\to\) +2 강화성공으로 인한 강화상태 변화
5 강화성공 +2 \(\to\) +3 강화성공으로 인한 강화상태 변화
6 강화성공 +3 \(\to\) +4 강화성공으로 인한 강화상태 변화
7 강화실패 +4 \(\to\) +4 강화실패로 인하여 강화상태 변화없음
8 강화성공 +4 \(\to\) +5 모든 강화 성공
9 - +5 \(\to\) +5 더 이상 강화시도 하지 않음
10 \(\dots\) \(\dots\) \(\dots\)

강화는 하루에 한 번씩만 시도할 수 있으며 시도가능한 기간은 7월1일부터 8월31일까지로 한정되어 있다고 하자. 따라서 방학동안 유저들은 총 62번 시도를 할 수 있다. 방학이 끝난이후 100명 유저중 대략 몇명정도 +5 강화상태에 있겠는가? 파이썬을 통한 시뮬레이션을 활용하여 추론하라. (단, +5강화에 성공하지 못한 모든 유저는 반드시 하루에 한번 강화를 시도해야 한다고 가정하자.)

(풀이1)

import numpy as np
np.random.seed(1)
sum(np.random.binomial(n=62, p=0.1, size=10000)>=5)/10000
0.7514

(풀이2)

class ExecutionSword():
    def __init__(self,prob):
        self.nuser=100000
        self.prob=prob
        self.attemptresult=None
        self.upgradestate=pd.DataFrame({'day0':[0]*self.nuser})
        self.failstate=pd.DataFrame({'day0':[0]*self.nuser})
        self.ratio=0
        self.day=0
    def addday(self):
        self.day=self.day+1            
    def attempt(self):
        self.attemptresult = np.random.binomial(n=1, p=self.prob, size=self.nuser)
    def update(self):
        # 강화상태 업데이트
        self.upgradestate['day%s' % self.day] = np.minimum(5,self.upgradestate['day%s' % (self.day-1)]+self.attemptresult)
        # 강화실패누적횟수 업데이트 
        self.failstate['day%s' % self.day]=self.failstate['day%s' % (self.day-1)]+(self.attemptresult==0)*1
        # 강화상태==5 or 강화상태==0 일 경우 강화실패누적횟수 초기화 
        self.failstate['day%s' % self.day][self.upgradestate['day%s' % self.day]== 0]=0
        self.failstate['day%s' % self.day][self.upgradestate['day%s' % self.day]== 5]=0
    def reset(self):
        # 실패횟수 = 2 인것을 찾아 index_ 에 저장 -> index_ 에 해당하는 유저의 강화횟수와 실패횟수를 모두 0으로 초기화 
        index_= self.failstate['day%s' % self.day]==2
        self.failstate['day%s' % self.day][index_] = 0
        self.upgradestate['day%s' % self.day][index_] = 0
    def arrangeprob(self):
        self.ratio=sum(self.upgradestate['day%s' % self.day]==5) / self.nuser
        if self.ratio > 0.5:
            self.prob = 0.9
# 1 
import pandas as pd
s1=ExecutionSword(0.1)
for i in range(62):
    s1.addday()
    s1.attempt()
    s1.update()
sum(s1.upgradestate.day62==5)/s1.nuser
0.75551

# 2. (70점)

강화성공확률을 40%로 수정한다. 강화에 누적2회 실패하면 강화상태가 초기화 된다고 하자. (따라서 강화실패 누적횟수를 카운트하는 변수가 필요하다) 단, 강화실패 누적횟수는 누적2회 달성시 0으로 초기화 된다. 또한 강화상태가 +0인 경우는 실패하여도 강화실패 누적횟수가 추가되지 않는다.

시도횟수 강화성공여부 강화상태 강화실패누적 비고
1 강화성공 +0 \(\to\) +1 0 \(\to\) 0 -
2 강화성공 +1 \(\to\) +2 0 \(\to\) 0 -
3 강화실패 +2 \(\to\) +2 0 \(\to\) 1 -
4 강화성공 +2 \(\to\) +3 1 \(\to\) 1 -
5 강화실패 +3 \(\to\) +0 1 \(\to\) 0 강화실패로 누적2회로 인한 초기화
6 강화실패 +0 \(\to\) +0 0 \(\to\) 0 강화실패 누적횟수 증가하지 않음
7 강화성공 +0 \(\to\) +1 0 \(\to\) 0 -
8 강화성공 +1 \(\to\) +2 0 \(\to\) 0 -
9 강화성공 +2 \(\to\) +3 0 \(\to\) 0 -
10 강화성공 +3 \(\to\) +4 0 \(\to\) 0 -
11 강화성공 +4 \(\to\) +5 0 \(\to\) 0 모든 강화 성공
12 - +5 \(\to\) +5 0 \(\to\) 0 더 이상 강화시도 하지 않음
13 \(\dots\) \(\dots\) \(\dots\) \(\dots\)

(1) 이 경우 62일의 방학뒤에 100명의 유저중 대략 몇명정도 +5 강화상태에 있겠는가? 시뮬레이션을 활용하여 추론하라. (단, +5강화에 성공하지 못한 모든 유저는 반드시 하루에 한번 강화를 시도해야 한다고 가정하자.)

(2) 31번째 시도 이후 대략 몇명의 유저가 +5 강화상태에 있겠는가?

# 2-1,2 
s2=ExecutionSword(0.4)
for i in range(62):
    s2.addday()
    s2.attempt()
    s2.update()
    s2.reset() ## 초기화가 되는 조건이 있으므로 문제1에서 reset함수만 추가하면 된다. 
# 2-1
sum(s2.upgradestate.day31==5)/s2.nuser
0.36392
# 2-2
sum(s2.upgradestate.day62==5)/s2.nuser
0.61803

(3) 100명의 유저중 50명이상의 유저가 +5 강화상태에 도달하는 순간 모든 유저의 강화성공확률을 90%로 증가시킨다고 하자. 62일의 방학뒤에 100명의 유저 중 몇명 정도가 +5 강화상태에 있겠는가?

# 2-3 
s3=ExecutionSword(0.4)
for i in range(62):
    s3.addday()
    s3.attempt()
    s3.update()
    s3.reset() ## 초기화가 되는 조건이 있으므로 reset함수 추가
    s3.arrangeprob() ## 전체유저의 50%가 강화성공하면 강화확률이 조정되는 조건이 있으므로 arragneprob 추가 
sum(s3.upgradestate.day62==5)/s3.nuser
0.9993