이번이벤을 기준으로 작성함

뱅가드 1.2% 인도미터블 2.0% 리벤지 2.5% 세 놈을 뽑으면 된다


저번에 10연차에 ur 뽑을 확률이 1-(1-1.2%)^10 = 약 11.3%라고 했었는데,

뽑아야될 갯수가 2개 이상으로 가면 엄청나게 복잡해진다

10연차안에 ur 뽑을 확률을 풀어서 생각하면

10연차동안 1개 나올 (나머지 9번은 모두 나오지 않을) 확률: 1.2%^1*98.8%^9 * 10C1 * 9C9 = 약 10.76%

10연차동안 2개 나올 (나머지 8번은 모두 나오지 않을) 확률: 1.2%^2*98.8%^8 * 10C2 * 8C8 = 약 0.58%

(...)

10연차동안 10개 나올 확률: 1.2%^10*98.8%^0 * 10C10 * 0C0 = 약 0.00000000000000000619%

가 되고, 이 값들을 모두 더하면

10.76449715559245312591%+0.58834296194533663993%+0.01905564249215664988%+0.00040502883839604219%+0.00000590325432480061%+0.00000005974953770041%+0.00000000041468736403%+0.00000000000188875824%+0.00000000000000509786%+0.00000000000000000619% =

11.37230675228878773453%

가 나오게 된다.

여기서 뽑아야 할 게 2개, 3개로 늘어나게 된다면 경우의 수는 엄청나게 늘어나고, 간단한 식으로 계산할 수가 없게 됨


그래서 파이썬의 힘을 빌려 계산기를 만들어봤음


//코드


from math import comb

우선 계산하는 과정에서 유용하게 쓸 콤비네이션 함수를 가져와준다.


p = 1/100

Pa = 1.2*p

Pb = 2.0*p

Pc = 2.5*p

Px = 1-(Pa+Pb+Pc)

ProbSum = 0

p는 뒤에 붙는 %를 간단하게 *p로 표현하기 위해서 만들었음

Pa는 뱅가드 확률, Pb는 인도미터블 확률, Pc는 리벤지의 확률이 된다

Px는 뱅가드, 인도미터블, 리벤지 중 아무것도 나오지 않을 확률임

ProbSum은 계산 과정에서의 모든 확률을 더해주기 위해서 만들었음


//반복문 시작

for a in range(1, 10):

    for b in range(1, 10):

        for c in range(1, 10):

            if a+b+c>10: break

            x = 10-(a+b+c)

a는 뱅가드를 뽑을 횟수, b는 인도미터블, c는 리벤지, x는 꽝이 나올 횟수이다

간단히 말하면 개수의 합이 10이 되는 모든 경우의 수를 만들어내는 것임

예시를 들자면

(a, b, c, x)라고 하면

(1, 1, 1, 7)은 뱅가드 1번, 인도미 1번, 리벤지 1번, 꽝 7번

(3, 5, 1, 1)은 뱅가드 3번, 인도미 5번, 리벤지 1번, 꽝 1번

이라고 생각하면 된다.

하지만 실제 확률 계산은 여기서 끝나면 안 됨

예를 들어

(1, 1, 1, 7)은 뱅가드 1번, 인도미 1번, 리벤지 1번, 7번

이 경우는

(뱅가드, 인도미, 리벤지, 꽝, 꽝, 꽝, 꽝, 꽝, 꽝, 꽝)

(꽝, 뱅가드, 꽝, 인도미, 리벤지, 꽝, 꽝, 꽝, 꽝, 꽝)

(인도미, 꽝, 꽝, 꽝, 꽝, 리벤지, 꽝, 꽝, 꽝, 뱅가드)

(...)

등등 여러 가짓수가 나올 수 있으므로 조합(콤비네이션)을 통해 모든 가짓수를 곱해줘야 함

적용하면

Prob = (Pa**a * Pb**b * Pc**c * Px**x) * comb(10, a) * comb(10-a, b) * comb(10-a-b, c) * comb(10-a-b-c, x)

(파이썬에서의 **은 제곱(^)이고, comb(10, a)는 10Ca를 의미한다)

Prob가 해당 경우에서의 확률이 된다

마지막으로 ProbSum에 해당 확률을 더해주면 됨

ProbSum = ProbSum+Prob

디버깅을 위한 변수 프린트 추가

print(a, b, c, x, '{:.20%}'.format(Prob))

'{:.20%}'.format(Prob))Prob라는 변수를 소수점 20번째 자리까지 나타내겠다는 뜻임


//반복문 종료

반복문이 끝났으면 이제 총 확률을 출력하는 것으로 마무리하면 됨

print('{:.10%}'.format(ProbSum))

이제 전체적인 코드를 보고 실행해보자


//코드

from math import comb


p = 1/100

Pa = 1.2*p

Pb = 2.0*p

Pc = 2.5*p

Px = 1-(Pa+Pb+Pc)

ProbSum = 0


for a in range(1, 10):

    for b in range(1, 10):

        for c in range(1, 10):

            if a+b+c>10: break

            x = 10-(a+b+c)

            Prob = (Pa**a * Pb**b * Pc**c * Px**x) * comb(10, a) * comb(10-a, b) * comb(10-a-b, c) * comb(10-a-b-c, x)

            ProbSum = ProbSum+Prob

            print(a, b, c, x, '{:.20%}'.format(Prob))


print('{:.10%}'.format(ProbSum))

//실행결과

1 1 1 7 0.28646106089271949902%

1 1 2 6 0.02658042717721417411%

1 1 3 5 0.00140935456931146215%

1 1 4 4 0.00004670448599255907%

1 1 5 3 0.00000099055113451875%

1 1 6 2 0.00000001313031726563%

1 1 7 1 0.00000000009945703125%

1 1 8 0 0.00000000000032958984%

1 2 1 6 0.02126434174177133443%

1 2 2 5 0.00169122548317375489%

1 2 3 4 0.00007472717758809452%

1 2 4 3 0.00000198110226903750%

1 2 5 2 0.00000003151276143750%

1 2 6 1 0.00000000027847968750%

1 2 7 0 0.00000000000105468750%

1 3 1 5 0.00090198692435933584%

1 3 2 4 0.00005978174207047561%

1 3 3 3 0.00000211317575364000%

1 3 4 2 0.00000004201701525000%

1 3 5 1 0.00000000044556750000%

1 3 6 0 0.00000000000196875000%

1 4 1 4 0.00002391269682819023%

1 4 2 3 0.00000126790545218400%

1 4 3 2 0.00000003361361220000%

1 4 4 1 0.00000000044556750000%

1 4 5 0 0.00000000000236250000%

1 5 1 3 0.00000040572974469888%

1 5 2 2 0.00000001613453385600%

1 5 3 1 0.00000000028516320000%

1 5 4 0 0.00000000000189000000%

1 6 1 2 0.00000000430254236160%

1 6 2 1 0.00000000011406528000%

1 6 3 0 0.00000000000100800000%

1 7 1 1 0.00000000002607206400%

1 7 2 0 0.00000000000034560000%

1 8 1 0 0.00000000000006912000%

2 1 1 6 0.01275860504506280343%

2 1 2 5 0.00101473528990425285%

2 1 3 4 0.00004483630655285670%

2 1 4 3 0.00000118866136142250%

2 1 5 2 0.00000001890765686250%

2 1 6 1 0.00000000016708781250%

2 1 7 0 0.00000000000063281250%

2 2 1 5 0.00081178823192340228%

2 2 2 4 0.00005380356786342804%

2 2 3 3 0.00000190185817827600%

2 2 4 2 0.00000003781531372500%

2 2 5 1 0.00000000040101075000%

2 2 6 0 0.00000000000177187500%

2 3 1 4 0.00002869523619382829%

2 3 2 3 0.00000152148654262080%

2 3 3 2 0.00000004033633464000%

2 3 4 1 0.00000000053468100000%

2 3 5 0 0.00000000000283500000%

2 4 1 3 0.00000060859461704832%

2 4 2 2 0.00000002420180078400%

2 4 3 1 0.00000000042774480000%

2 4 4 0 0.00000000000283500000%

2 5 1 2 0.00000000774457625088%

2 5 2 1 0.00000000020531750400%

2 5 3 0 0.00000000000181440000%

2 6 1 1 0.00000000005475133440%

2 6 2 0 0.00000000000072576000%

2 7 1 0 0.00000000000016588800%

3 1 1 5 0.00032471529276936089%

3 1 2 4 0.00002152142714537121%

3 1 3 3 0.00000076074327131040%

3 1 4 2 0.00000001512612549000%

3 1 5 1 0.00000000016040430000%

3 1 6 0 0.00000000000070875000%

3 2 1 4 0.00001721714171629697%

3 2 2 3 0.00000091289192557248%

3 2 3 2 0.00000002420180078400%

3 2 4 1 0.00000000032080860000%

3 2 5 0 0.00000000000170100000%

3 3 1 3 0.00000048687569363866%

3 3 2 2 0.00000001936144062720%

3 3 3 1 0.00000000034219584000%

3 3 4 0 0.00000000000226800000%

3 4 1 2 0.00000000774457625088%

3 4 2 1 0.00000000020531750400%

3 4 3 0 0.00000000000181440000%

3 5 1 1 0.00000000006570160128%

3 5 2 0 0.00000000000087091200%

3 6 1 0 0.00000000000023224320%

4 1 1 4 0.00000516514251488909%

4 1 2 3 0.00000027386757767174%

4 1 3 2 0.00000000726054023520%

4 1 4 1 0.00000000009624258000%

4 1 5 0 0.00000000000051030000%

4 2 1 3 0.00000021909406213740%

4 2 2 2 0.00000000871264828224%

4 2 3 1 0.00000000015398812800%

4 2 4 0 0.00000000000102060000%

4 3 1 2 0.00000000464674575053%

4 3 2 1 0.00000000012319050240%

4 3 3 0 0.00000000000108864000%

4 4 1 1 0.00000000004927620096%

4 4 2 0 0.00000000000065318400%

4 5 1 0 0.00000000000020901888%

5 1 1 3 0.00000005258257491297%

5 1 2 2 0.00000000209103558774%

5 1 3 1 0.00000000003695715072%

5 1 4 0 0.00000000000024494400%

5 2 1 2 0.00000000167282847019%

5 2 2 1 0.00000000004434858086%

5 2 3 0 0.00000000000039191040%

5 3 1 1 0.00000000002365257646%

5 3 2 0 0.00000000000031352832%

5 4 1 0 0.00000000000012541133%

6 1 1 2 0.00000000033456569404%

6 1 2 1 0.00000000000886971617%

6 1 3 0 0.00000000000007838208%

6 2 1 1 0.00000000000709577294%

6 2 2 0 0.00000000000009405850%

6 3 1 0 0.00000000000005016453%

7 1 1 1 0.00000000000121641822%

7 1 2 0 0.00000000000001612431%

7 2 1 0 0.00000000000001289945%

8 1 1 0 0.00000000000000193492%

0.3536096567%

10연차 내에 올클할 확률은 0.3536096567%가 나왔음

이제 뽑아야 될 캐릭터의 종류 수, 뽑을 횟수, 확률을 변경할 수 있게 코드를 일반화하면



//완성본

from math import comb

import itertools as it

import readchar


p = 1/100


Pn = list(map(float, input("Input Probabilities of Each Items (Unit: %): ").split()))

Cnt = int(input("Input Number of Pulls: "))


Pn = [X*p for X in Pn]

Px = 1-sum(Pn)

_Pn = Pn

_Pn.append(Px)

ProbSum = 0


LEN = len(Pn)

Combinations = [

    X for X in it.product(range(1, Cnt+1), repeat=LEN-1)

    if sum(X) <= Cnt

]


for C in Combinations:

    C = list(C)

    C.append(Cnt-sum(C))

    _Cnt = Cnt

    Prob = 1

    for Pi, n in zip(_Pn, C):

        Prob = Prob * (Pi**n * comb(_Cnt, n))

        _Cnt = _Cnt-n

    ProbSum = ProbSum + Prob


print('{:.10%}'.format(ProbSum))


print("\nPress Any Key To Exit...")

k = readchar.readchar()

//실행결과

Input Probabilities of Each Items (Unit: %): 1.2 2.0 2.5

Input Number of Pulls: 10

0.3536096567%

Input Probabilities of Each Items (Unit: %): 1.2 2.0 2.5

Input Number of Pulls: 100

55.7761065354%

10연차 이내로 졸업할 확률은 약 0.35%,

100연차 이내로 졸업할 확률은 약 55.7%가 나왔음

횟수가 늘어나면 계산해야 될 가짓수가 기하급수적으로 늘어나서 100 이상은 하지 않는 게 좋음 (100뽑 계산하는데 약 5초 걸림)


GitHub : https://github.com/CcRr0/ProbabilityCalculator

코드 : https://github.com/CcRr0/ProbabilityCalculator/blob/master/main.py

실행파일 : https://github.com/CcRr0/ProbabilityCalculator/raw/master/dist/ProbabilityCalculator.exe