03. 제비뽑기와 조합, 로또의 세계(Combination)
1. 학습 목표 (Learning Objectives)
- 계급장 떼고, 오로지 ‘누가 뽑혔는가’ 그 결과물만 중요한 평등의 민주주의 수학 기호 조합(Combination, $\mathbf{_nC_r}$)의 파워를 경험합니다.
- 대한민국을 가장 열광하게 만드는 숫자 게임인 ‘로또(Lotto 6/45)’ 등 무작위 확률의 경우의 수를 파이썬
itertools.combinations엔진으로 직접 뽑아보고 난수의 기하급수적 방대함을 체험합니다.
2. 순서는 부질없다, 오직 뭉쳐라! 조합($_nC_r$)
지난 시간에 배운 순열(P)은 “누가 앞자리 탑승이고 누가 뒷자리야?”를 미친 듯이 따지는 자존심 경쟁이었습니다.
하지만 오늘 배울 수학 기호 명칭 $\mathbf{C}$ (조합: Combination) 은 완전히 다른 평화로운 세상입니다.
조합의 룰: “우린 계급 다 뗐다. A가 먼저 나오든 B가 먼저 나오든, 어차피 안에는 (A, B) 둘이 들어있으니까 자리를 바꾸는 건 똑같은 경우의 수로 취급(중복 처리) 해서 폐기한다!”
★ 로또 당첨의 원리
당신이 로또 당첨 번호 기계 캡슐 속으로 들어갔습니다.
1번 공과 7번 공을 순서대로 부르든, 반대로 7번 불리고 이어서 1번이 불리든 어차피 내 당첨 카운팅에는 [1, 7] 구성원 두 명이 존재한다는 사실 자체가 중요합니다. 자리가 뒤틀리건 말건 중요하지 않은 이런 형태를 수학에서는 ‘제비뽑기’라고 부릅니다.
- 조합의 계산식 ($_nH_r$): 앞에서 배운 순열($_nP_r$)로 순서 경쟁을 일으켜 갯수를 뽑은 뒤… 이미 뽑힌 놈들끼리 지지고 볶고 순서를 바꾸는 팩토리얼($r!$) 만큼의 분모를 칼같이 나누어버려(÷) 중복을 모조리 제거합니다! (ex. $_5C_2 = \frac{5 \times 4}{2 \times 1} = \mathbf{10\text{가지}}$)
3. 파이썬 Combination 로또 시뮬레이터 (Python)
이제 파이썬으로 45개의 숫자에서 6개를 공평하게 뽑는 itertools.combinations 캡슐 코딩을 돌려보겠습니다.
이 코드는 파이썬 언어로 로또 복권의 무작위성이 기하급수적으로 얼마나 희박한 희망을 제시하는지 자비 없이 보여주는 통계 엔진입니다.
import itertools
# 1. 아둥바둥 순서 다 떼고, 공평하게 대표 팀(조합)을 뽑는 파이썬 엔진 준비!
# 45개 로또 공 배럴 만들기 (1~45)
lotto_balls = list(range(1, 46))
pick_count = 6 # 6개 뽑기
print("🎉 [슈퍼 파이썬 로또 시뮬레이터 가동]")
print(f"👉 전체 로또 공 갯수: {len(lotto_balls)}개 | 뽑는 방식: 조합(Combination, 순서 신경안씀)")
print("-" * 50)
# 2. 파이썬 조합 모듈 폭발 가동! itertools.combinations
# 45개 중 6개를 순서 무관 무차별로 뽑는 모든 우주의 경우의 수를 리스트 메모리에 때려 박습니다.
# (※ 주의: 이 코드의 리스트 변환(list)은 컴퓨터 메모리를 순식간에 수백 메가바이트 잡아먹을 만큼 무지막지한 덩어리입니다.)
# 이 연산을 위해선 내부적으로 (_45C_6) 수학 공식을 풉니다!
all_lotto_cases = list(itertools.combinations(lotto_balls, pick_count))
# 결과 산출 모니터링
total_odds = len(all_lotto_cases)
print(f"😱 45개 중 순서 없이 6개를 뽑는 전체 경우의 수(_45C_6): {total_odds:,} 가지!!")
print(f"💸 당신이 1등에 당첨될 확률: 1 / {total_odds:,} (약 {(1/total_odds)*100:.8f}%)")
print("-" * 50)
print(f"[기계가 우연히 뽑아낸 경우의 수 아주 앞부분 3조각]")
for i in range(3):
print(f"조합 #{i+1:02d}: {all_lotto_cases[i]}")
print("\n[기계가 우연히 뽑아낸 경우의 수 끄트머리 3조각]")
for i in range(1, 4):
print(f"조합 #{total_odds - i:02d}: {all_lotto_cases[-i]}")
파이썬의 비정하고 냉혹한 수학 실행 결과:
🎉 [슈퍼 파이썬 로또 시뮬레이터 가동]
👉 전체 로또 공 갯수: 45개 | 뽑는 방식: 조합(Combination, 순서 신경안씀)
--------------------------------------------------
😱 45개 중 순서 없이 6개를 뽑는 전체 경우의 수(_45C_6): 8,145,060 가지!!
💸 당신이 1등에 당첨될 확률: 1 / 8,145,060 (약 0.00001228%)
--------------------------------------------------
[기계가 우연히 뽑아낸 경우의 수 아주 앞부분 3조각]
조합 #01: (1, 2, 3, 4, 5, 6)
조합 #02: (1, 2, 3, 4, 5, 7)
조합 #03: (1, 2, 3, 4, 5, 8)
[기계가 우연히 뽑아낸 경우의 수 끄트머리 3조각]
조합 #8145059: (40, 41, 42, 43, 44, 45)
조합 #8145058: (39, 41, 42, 43, 44, 45)
조합 #8145057: (39, 40, 42, 43, 44, 45)
수학 시간에 교과서로 배우던 그 귀여웠던 ‘대표 2명 뽑기’나 ‘제비뽑기 조합기호($_nC_r$)’가, 숫자가 불과 45개로 뻥튀기되자마자 자그마치 814만 번의 중복 없는 경우의 수를 파괴적으로 토해내는 괴물이라는 사실을 파이썬 코딩은 잔혹할 정도로 투명하게 보여줍니다.
4. 학습 정리 (Summary)
- 조합 ($\mathbf{_nC_r}$): 선출된 원소 구성 멤버 간의 ‘서열이나 줄 선 순서 교체’를 완벽하게 무효화 시켜, 사실상 구성된 멤버 팩의 집단 자체만 하나(1)의 온전한 경우로 카운팅하는 대표자 제비뽑기 산술 기호입니다.
- 파이썬
combinations모듈: 내부에서 자동으로 조합($C$) 수학 분모 나누기(r!) 공식을 처리하여, $N$개 중 $R$개를 순서 다 무시하고 중복 조합만 걸러낸 아주 기하급수적으로 큰 쌍둥이 데이터 팩들을 일괄 생성해 주는 예측 시뮬레이터 프레임워크입니다.
서브목차