- 문제 : 시험 문제

import pandas as pd
import numpy as np

1번 문제

class execution_sword():
    
    def __init__(self):
        self.upgradestate = pd.DataFrame({'day0':[0] * 100})
        self.prob = 0.3
        self.day = 0
        
    def add_day(self):
        self.day = self.day + 1  ## 날짜를 하루 더한다
        
    def attempt(self):
        self.attemptresult = np.random.binomial(n = 1, p = self.prob, size = 100) 
           
    def update(self):
        self.upgradestate['day%s' % self.day] = np.minimum(self.upgradestate['day%s' % (self.day - 1)] + self.attemptresult, 5) ## +5이후로는 증가하지 않는다  
        self.ratio = sum(self.upgradestate.loc[:, 'day%s' % self.day] == 5) / 100 
        
    def return_ratio(self):
        return self.ratio ## ratio(성공한 사람 수 / 전체 사람 수)를 리턴한다
#1-(1)
test1 = execution_sword()

for test1.day in range(1, 63):
    test1.attempt()
    test1.update()
    
100 * test1.ratio ## 62일후 100명중 몇명이 +5강화 상태인가?

## 시뮬레이션 결과 100명이였다
100.0

- 위에처럼 test.i를 함수 외부에서 조작하는 것은 좋지 않다

- 마찬가지로 test1 클래스의 멤버변수(ratio)에 직접 접근하는 것도 좋지 않다

- 이를 조작할 수 있는 함수를 새로 만들고 코드를 다시 구현하자

test_1 = execution_sword()

for k in range(1, 63):
    test_1.add_day()
    test_1.attempt()
    test_1.update()
    
100 * test_1.return_ratio()
100.0

2번 문제

class execution_sword2(execution_sword):
    
    def __init__(self):
        super().__init__() ## 함수 오버라이딩
        self.prob = 0.7
        self.failstate = pd.DataFrame({'day0':[0] * 100})
        
    def update(self):
        super().update() ## 함수 오버라이딩
        self.failstate['day%s' % self.day] = self.failstate['day%s' % (self.day - 1)] + (self.attemptresult == 0) * 1
        
        for j in range(100):
            if self.upgradestate.iloc[j, self.day] == 0:
                self.failstate.iloc[j, self.day] = self.failstate.iloc[j, self.day] - 1 
            ## i-1번째 + 강화시도(0 or 1) = i번째
            ## i, i-1번째 강화상태가 0이라는 의미는 i-1째에 시도한 강화가 실패했다는 의미
            ## upgradestate가 0이라는 의미는 실패했다는 것이므로 실패횟수가 하나 쌓인다
            ## +0에서는 실패횟수가 쌓이지 않으므로 failstate값을 하나 뺀다
            
            if (self.upgradestate.iloc[j, self.day] == 5) and (self.attemptresult[j] == 0):
            ## i-1번째 + 강화시도(0 or 1) = i번째 
            ## i번째가 +5강화이면서 i-1번째 시도한 강화가 실패라는 의미는
            ## i-1번째가 +5강화였다는 의미이다. 그러므로 i번째 실패횟수가 +1 됐을것이다
            ## +5강화에서는 강화를 도전하지 않을 것이다
            ## 그러므로 i번째 실패횟수를 1을 감소시킨다
                self.failstate.iloc[j, self.day] = self.failstate.iloc[j, self.day] - 1 
            ## +5에서는 강화를 시도하지 않을것이므로 
            ## 만약 실패했다면 failstate값을 하나 뺀다
                
    def reset(self): 
        for j in range(100):
            if (self.upgradestate.iloc[j, self.day] > 0) and (self.upgradestate.iloc[j, self.day] < 5):     
                if self.failstate.iloc[j, self.day] == 2:
                    self.failstate.iloc[j, self.day] = 0
                    self.upgradestate.iloc[j, self.day] = 0
            ## 실패스택이 2라면 실패스택을 0으로 바꾸고 강화상태를 +0으로 바꾼다 
            
    def arrangeprobt(self):
        if self.ratio >= 0.5:
            self.prob = 0.9
            
        ## +5강 비율이 50%이상이라면 전체유저의 강화 성공확률을 90%로 바꾼다
    
    @property
    def return_ratio(self):
        return self.ratio  

- 위에서 멤버변수 ratio를 반환하는 return_ratio라는 함수를 만들었다

- 그런데 전에는 인스턴스.ratio를 사용했는데 이제는 인스턴스.return_ratio()를 써야한다

- 전에 사용하던 것처럼 값으로 쓰고싶다(괄호를 생략하여 메소드를 값처럼 사용하고 싶다)

- @property를 사용!

#2-(1)
test2 = execution_sword2()

for k in range(1, 63):
    test2.add_day()
    test2.attempt()
    test2.update()
    test2.reset()
    
100 * test2.return_ratio  ## 괄호 생략 가능 ## 그런데 메소드 이름이 return_ratio라 괄호가 있는 것이 자연스러운 것 같음

## 시뮬레이션 결과 100명이였다       
100.0
#2-(2)
test3 = execution_sword2()

for k in range(1, 32):
    test3.add_day()
    test3.attempt()
    test3.update()
    test3.reset()

100 * test3.return_ratio  ## 31일후 100명중 몇명이 +5강화 상태인가?

## 시뮬레이션 결과 99명이였다
99.0
#2-(3)
test4 = execution_sword2()

for k in range(1, 63):
    test4.add_day()
    test4.attempt()
    test4.update()
    test4.reset()
    test4.arrangeprobt()
    
100 * test4.return_ratio  ## 과반수가 +5강화 일때 성공확률을 0.9로 바꾼다, 62일후 100명중 몇명이 +5강화 상태인가?

## 시뮬레이션 결과 100명이였다
100.0

3번 문제

- 다음문장을 잘 읽고 참 거짓을 판단하여라 (10점)

1. tuple은 원소의 값을 임의로 바꿀 수 있다 ---> 거짓

2. class 에 정의된 함수(=메서드)는 self 만을 인자로 받을수 있다 ---> 거짓