|
| 1 | +""" |
| 2 | +Project Euler Problem 205: https://projecteuler.net/problem=205 |
| 3 | +
|
| 4 | +Peter has nine four-sided (pyramidal) dice, each with faces numbered 1, 2, 3, 4. |
| 5 | +Colin has six six-sided (cubic) dice, each with faces numbered 1, 2, 3, 4, 5, 6. |
| 6 | +
|
| 7 | +Peter and Colin roll their dice and compare totals: the highest total wins. |
| 8 | +The result is a draw if the totals are equal. |
| 9 | +
|
| 10 | +What is the probability that Pyramidal Peter beats Cubic Colin? |
| 11 | +Give your answer rounded to seven decimal places in the form 0.abcdefg |
| 12 | +""" |
| 13 | + |
| 14 | +from itertools import product |
| 15 | + |
| 16 | + |
| 17 | +def total_frequency_distribution(sides_number: int, dice_number: int) -> list[int]: |
| 18 | + """ |
| 19 | + Returns frequency distribution of total |
| 20 | +
|
| 21 | + >>> total_frequency_distribution(sides_number=6, dice_number=1) |
| 22 | + [0, 1, 1, 1, 1, 1, 1] |
| 23 | +
|
| 24 | + >>> total_frequency_distribution(sides_number=4, dice_number=2) |
| 25 | + [0, 0, 1, 2, 3, 4, 3, 2, 1] |
| 26 | + """ |
| 27 | + |
| 28 | + max_face_number = sides_number |
| 29 | + max_total = max_face_number * dice_number |
| 30 | + totals_frequencies = [0] * (max_total + 1) |
| 31 | + |
| 32 | + min_face_number = 1 |
| 33 | + faces_numbers = range(min_face_number, max_face_number + 1) |
| 34 | + for dice_numbers in product(faces_numbers, repeat=dice_number): |
| 35 | + total = sum(dice_numbers) |
| 36 | + totals_frequencies[total] += 1 |
| 37 | + |
| 38 | + return totals_frequencies |
| 39 | + |
| 40 | + |
| 41 | +def solution() -> float: |
| 42 | + """ |
| 43 | + Returns probability that Pyramidal Peter beats Cubic Colin |
| 44 | + rounded to seven decimal places in the form 0.abcdefg |
| 45 | +
|
| 46 | + >>> solution() |
| 47 | + 0.5731441 |
| 48 | + """ |
| 49 | + |
| 50 | + peter_totals_frequencies = total_frequency_distribution( |
| 51 | + sides_number=4, dice_number=9 |
| 52 | + ) |
| 53 | + colin_totals_frequencies = total_frequency_distribution( |
| 54 | + sides_number=6, dice_number=6 |
| 55 | + ) |
| 56 | + |
| 57 | + peter_wins_count = 0 |
| 58 | + min_peter_total = 9 |
| 59 | + max_peter_total = 4 * 9 |
| 60 | + min_colin_total = 6 |
| 61 | + for peter_total in range(min_peter_total, max_peter_total + 1): |
| 62 | + peter_wins_count += peter_totals_frequencies[peter_total] * sum( |
| 63 | + colin_totals_frequencies[min_colin_total:peter_total] |
| 64 | + ) |
| 65 | + |
| 66 | + total_games_number = (4 ** 9) * (6 ** 6) |
| 67 | + peter_win_probability = peter_wins_count / total_games_number |
| 68 | + |
| 69 | + rounded_peter_win_probability = round(peter_win_probability, ndigits=7) |
| 70 | + |
| 71 | + return rounded_peter_win_probability |
| 72 | + |
| 73 | + |
| 74 | +if __name__ == "__main__": |
| 75 | + print(f"{solution() = }") |
0 commit comments