로또 번호 생성기
조합 1: 03 07 13 21 25 28 (핫 넘버: 1개)
조합 2: 04 19 20 21 38 45 (핫 넘버: 1개)
조합 3: 02 03 13 16 38 43 (핫 넘버: 1개)
조합 4: 10 13 14 31 33 35 (핫 넘버: 3개)
조합 5: 06 09 13 18 38 40 (핫 넘버: 3개)
* 무작위로 생성된 번호이며, 당첨을 보장하지 않습니다.
#!/opt/bitnami/venvs/lotto/bin/python3
import random
import pandas as pd
import pymysql
import os
from dotenv import load_dotenv
from collections import Counter
class LottoGenerator:
def __init__(self):
# 데이터베이스 연결 정보 로드
load_dotenv()
self.db_config = {
'host': os.getenv('DB_HOST'),
'port': int(os.getenv('DB_PORT', 3306)),
'user': os.getenv('DB_USER'),
'password': os.getenv('DB_PASSWORD'),
'db': os.getenv('DB_NAME'),
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor
}
self.lotto_data = None
self.number_frequency = None
self.pair_frequency = None
def load_lotto_data(self):
"""데이터베이스에서 로또 당첨 번호 데이터 로드"""
try:
conn = pymysql.connect(**self.db_config)
with conn.cursor() as cursor:
sql = "SELECT count, `1`,`2`,`3`,`4`,`5`,`6` FROM lotto ORDER BY count ASC"
cursor.execute(sql)
rows = cursor.fetchall()
self.lotto_data = pd.DataFrame(rows)
print(f"데이터베이스에서 {len(self.lotto_data)}개의 로또 당첨 번호를 로드했습니다.")
return True
except Exception as e:
print(f"데이터베이스 연결 오류: {str(e)}")
return False
def analyze_statistics(self):
"""당첨 번호 통계 분석"""
if self.lotto_data is None:
if not self.load_lotto_data():
print("통계 분석을 위한 데이터 로드에 실패했습니다.")
return False
# 모든 당첨 번호를 하나의 리스트로 변환
all_numbers = []
for _, row in self.lotto_data.iterrows():
all_numbers.extend([row['1'], row['2'], row['3'], row['4'], row['5'], row['6']])
# 번호별 출현 빈도 계산
self.number_frequency = Counter(all_numbers)
# 번호 쌍(페어) 빈도 분석
pairs = []
for _, row in self.lotto_data.iterrows():
numbers = [row['1'], row['2'], row['3'], row['4'], row['5'], row['6']]
for i in range(len(numbers)):
for j in range(i+1, len(numbers)):
pairs.append((min(numbers[i], numbers[j]), max(numbers[i], numbers[j])))
self.pair_frequency = Counter(pairs)
return True
def calculate_weights(self):
"""번호별 가중치 계산"""
if self.number_frequency is None:
self.analyze_statistics()
weights = {}
max_freq = max(self.number_frequency.values())
min_freq = min(self.number_frequency.values())
for num in range(1, 46):
freq = self.number_frequency.get(num, 0)
# 빈도수에 따른 가중치 계산 (1-3 범위로 정규화)
if max_freq > min_freq:
weight = 1 + 2 * (freq - min_freq) / (max_freq - min_freq)
else:
weight = 1.0
weights[num] = weight
return weights
def get_hot_numbers(self, count=10):
"""자주 나오는 번호 추출"""
if self.number_frequency is None:
self.analyze_statistics()
return [num for num, _ in self.number_frequency.most_common(count)]
def get_top_pairs(self, count=10):
"""자주 함께 나오는 번호 쌍 추출"""
if self.pair_frequency is None:
self.analyze_statistics()
return [pair for pair, _ in self.pair_frequency.most_common(count)]
def weighted_sample(self, population, weights, k):
"""가중치 기반 샘플링"""
population_list = list(population)
weights_list = [weights.get(i, 1.0) for i in population_list]
return random.choices(population_list, weights=weights_list, k=k)
def generate_numbers(self, games=5):
"""통계 기반 로또 번호 생성"""
weights = self.calculate_weights()
hot_numbers = self.get_hot_numbers()
top_pairs = self.get_top_pairs()
results = []
for _ in range(games):
numbers = []
# 70% 확률로 인기 페어 중 하나를 우선 포함
if top_pairs and random.random() < 0.7:
pair = random.choice(top_pairs)
numbers.extend(pair)
# 나머지 번호 선택
remaining = 6 - len(numbers)
candidates = [n for n in range(1, 46) if n not in numbers]
selected = self.weighted_sample(candidates, weights, remaining)
numbers.extend(selected)
# 중복 제거 및 부족한 숫자 추가
numbers = list(set(numbers))
while len(numbers) < 6:
additional = self.weighted_sample(range(1, 46), weights, 1)[0]
if additional not in numbers:
numbers.append(additional)
# 정렬
numbers.sort()
results.append(numbers)
return results, hot_numbers
def generate_lotto():
generator = LottoGenerator()
results, hot_numbers = generator.generate_numbers()
print("\n통계 기반 로또 번호 추천")
print("-" * 30)
for i, numbers in enumerate(results, 1):
hot_count = sum(1 for num in numbers if num in hot_numbers)
print(f"조합 {i}: {' '.join(f'{num:02d}' for num in numbers)} (핫 넘버: {hot_count}개)")
print("-" * 30)
print(f"핫 넘버 (상위 10개): {', '.join(f'{num:02d}' for num in hot_numbers)}")
if __name__ == "__main__":
generate_lotto()