Вы едете на конвент по настольным играм. Скорее всего, там будет достаточно жесткая конкуренция и поэтому вы решили узнать немного больше о теории вероятности, поскольку вы подозреваете, что в ближайшее время вам придется много раз бросать кости . Обычно, при использовании нескольких кубиков, вы просто кидаете их, а результат суммируете. Для того, чтобы начать исследования по вероятности выпадения тех или иных значений игральных костей, напишите функцию, которая принимает на вход число кубиков, число сторон на кубике и исследуемый номер, а возвращает вероятность получения заданного значения. Результат должен возвращаться с точностью в четыре цифры после запятой - ±0.0001. Например, если вы бросили 2 шестигранных кубика, вероятность что выпадет 3 составляет 2/36 или 5,56% в процентном соотношении, соответственно ваша функция должна вернуть число, записанное как ≈0.0556. В дроби 2/36 числитель, это количество возможных вариаций получения числа 3 на двух кубиках (1;2 или 2;1), а знаменатель, это количество возможных комбинаций для 2-х шистигранных кубиков (6**2) Для каждого теста, предполагается, что все кости одинаковы и пронумерованы от 1 и до числа сторон, заданных входными данными включительно. Таким образом, 4-сторонний кубик (D4) будет иметь равные шансы на выпадения чисел 1, 2, 3 или 4. И эти шансы можно оценить как 1/4. А 20-сторонний кубик (D20) будет иметь равные шансы на выпадение любого числа от 1 до 20, которые можно оценить как 1/20. Советы: Будьте осторожны, если вы захотите решить эту задачу путем перебора всех возможных вариаций - вам возможно придется очень долго ждать! Например для входных данных (10, 10, 50) - время ожидания может достигать нескольких десятков минут! Используйте принцип динамического программирования, например как здесь. На входе: Три аргумента. Количество кубиков, количество сторон на кубике и исследуемое значение как целые числа. На выходе: Вероятность получения заданного значения за один бросок игральных костей, как число с плавающей запятой. Пример: probability(2, 6, 3) == 0.0556 # на 2-х шестигранных кубиках вероятность выпадения 3 равна 5.56% probability(2, 6, 4) == 0.0833 probability(2, 6, 7) == 0.1667 probability(2, 3, 5) == 0.2222 # на 2-х трехгранных кубиках вероятность выпадения 5 равна 22.22% probability(2, 3, 7) == 0 # на 2-х трехгранных кубиках вы можете выкинуть максимум 6 (3;3) probability(3, 6, 7) == 0.0694 probability(10, 10, 50) == 0.0375 Код probability(2, 6, 3) == 0.0556 # на 2-х шестигранных кубиках вероятность выпадения 3 равна 5.56% probability(2, 6, 4) == 0.0833 probability(2, 6, 7) == 0.1667 probability(2, 3, 5) == 0.2222 # на 2-х трехгранных кубиках вероятность выпадения 5 равна 22.22% probability(2, 3, 7) == 0 # на 2-х трехгранных кубиках вы можете выкинуть максимум 6 (3;3) probability(3, 6, 7) == 0.0694 probability(10, 10, 50) == 0.0375 итак, как решить эту задачу? я вот набросал код, он правильлный но пиздец долго будет считать if dice_number == 10: for i in range(1,sides+1): for j in range(1,sides+1): for k in range(1,sides+1): for q in range(1,sides+1): for w in range(1,sides+1): for e in range(1,sides+1): for r in range(1,sides+1): for t in range(1,sides+1): for y in range(1,sides+1): if i+j+k+q+w+e+r+t+y == target: co += 1 Код if dice_number == 10: for i in range(1,sides+1): for j in range(1,sides+1): for k in range(1,sides+1): for q in range(1,sides+1): for w in range(1,sides+1): for e in range(1,sides+1): for r in range(1,sides+1): for t in range(1,sides+1): for y in range(1,sides+1): if i+j+k+q+w+e+r+t+y == target: co += 1 так вот, как сделать по другому чтобы быстро работало
Тут мало кто поможет с кодингом. Одни школьники. Советую прочекать CyberForum или StackoverFlow, там точно есть кто шарит, в отличии от лулза
def probability(dice_number, sides, target): if sides*dice_number<target or target == 0: return 0 if dice_number == 1: return dice_number/sides pr = (1/sides ** dice_number) print(pr) ver = 0 if target > dice_number*sides//2+1: for i in range(dice_number,(dice_number*sides)//2+2): ver += pr for i in range((dice_number*sides)//2+2,target+1): ver -= pr print(ver) if dice_number>2: return ver*dice_number return ver else: for i in range(dice_number,target+1): ver += pr if dice_number > 2: return ver*dice_number return ver Код def probability(dice_number, sides, target): if sides*dice_number<target or target == 0: return 0 if dice_number == 1: return dice_number/sides pr = (1/sides ** dice_number) print(pr) ver = 0 if target > dice_number*sides//2+1: for i in range(dice_number,(dice_number*sides)//2+2): ver += pr for i in range((dice_number*sides)//2+2,target+1): ver -= pr print(ver) if dice_number>2: return ver*dice_number return ver else: for i in range(dice_number,target+1): ver += pr if dice_number > 2: return ver*dice_number return ver --- Сообщение объединено с предыдущим 1 авг 2019 вот что получилось --- Сообщение объединено с предыдущим 1 авг 2019
from functools import lru_cache @lru_cache(maxsize=None) def probability(dice_number, sides, target): if dice_number == 1: return (1 <= target <= sides**dice_number)/sides return sum([probability(dice_number-1, sides, target-x) for x in range(1, sides+1)])/sides Код from functools import lru_cache @lru_cache(maxsize=None) def probability(dice_number, sides, target): if dice_number == 1: return (1 <= target <= sides**dice_number)/sides return sum([probability(dice_number-1, sides, target-x) for x in range(1, sides+1)])/sides