import time
import random
# --- 1. Генераторы (из предыдущих заданий) ---
def bad_lcg_gen(n, seed=12345):
"""Плохой LCG (младшие биты предсказуемы)"""
m = 2**31
a = 1103515245
c = 12345
x = seed
for _ in range(n):
x = (a * x + c) % m
# ВАЖНО: для симуляции игры нам нужен только бит "выиграл/проиграл"
# Берем остаток от деления на 2. У плохого LCG он будет чередоваться!
yield x % 2
def park_miller_gen(n, seed=12345):
"""Хороший генератор Park-Miller"""
m = 2**31 - 1
a = 16807
x = seed
for _ in range(n):
x = (a * x) % m
# Для честного сравнения тоже берем остаток от деления на 2
yield x % 2
# --- 2. Логика игры ---
def play_game(get_rand_bit, start_coins=10, max_throws=50):
"""
Симулирует ОДНУ игру.
Возвращает True, если игрок разорился (дошел до 0).
"""
coins = start_coins
throws = 0
while coins > 0 and throws < max_throws:
# get_rand_bit() возвращает 0 или 1
# Допустим, 1 - это выигрыш (+1), 0 - проигрыш (-1)
if get_rand_bit() == 1:
coins += 1
else:
coins -= 1
throws += 1
return coins == 0
# --- 3. Проведение эксперимента ---
def run_experiment(gen_func, num_simulations, name):
start_time = time.time()
ruin_count = 0
# Создаем бесконечный итератор из генератора
# (нам нужно много чисел, поэтому генерируем с запасом)
gen = gen_func(num_simulations * 50)
for _ in range(num_simulations):
# Для каждой игры берем следующие числа из генератора
if play_game(lambda: next(gen)):
ruin_count += 1
end_time = time.time()
prob = (ruin_count / num_simulations) * 100
print(f"--- {name} ---")
print(f"Симуляций: {num_simulations}")
print(f"Разорилось: {prob:.2f}% (Теория: ~16-17%)")
print(f"Время выполнения: {end_time - start_time:.4f} сек\n")
return prob
# Количество прогонов для статистики (чем больше, тем точнее)
N_SIMS = 100000
print("Запуск симуляции...\n")
# Запуск с плохим генератором
prob_bad = run_experiment(bad_lcg_gen, N_SIMS, 'ПЛОХОЙ LCG (младший бит)')
# Запуск с хорошим генератором
prob_good = run_experiment(park_miller_gen, N_SIMS, 'ХОРОШИЙ Park-Miller')