|
| 1 | +import numpy as np |
| 2 | + |
| 3 | +def outcome_of_rolling_n_sided_dice_k_time(n_side: int, k_time: int) -> list: |
| 4 | + """ |
| 5 | + Outcomes for rolling an N-sided dice K times. |
| 6 | + |
| 7 | + This function returns a list. The first element is an array. |
| 8 | + That array contains indexes. |
| 9 | + The second element is another array. |
| 10 | + That array contains probabilities for each index value. |
| 11 | +
|
| 12 | + Algorithm Explanation: |
| 13 | + |
| 14 | + 1. Explanation of range: |
| 15 | + When we are rolling a six-sided dice the range becomes |
| 16 | + 1 to 6. |
| 17 | + While rolling 5 times range becomes 2 to 12. |
| 18 | + The sum outcomes becomes 5 when all rolling finds 1. |
| 19 | + 30 happens when all rolling finds 6. |
| 20 | + 1 is the minimum and 6 is the maximum of side values |
| 21 | + for a 6 sided dice. Therefore, the range is 5 to 30. |
| 22 | + Therefore, the range is k to n*k. |
| 23 | + |
| 24 | + 2. Explanation of probability distribution: |
| 25 | + Say we are rolling a six-sided dice 2 times. |
| 26 | + for 0 roll, the outcome is 0 with probability 1. |
| 27 | + For the first roll, the outcome is 1 to 6 equally distributed. |
| 28 | + |
| 29 | + For the second roll, each previous outcome (1-6) will face |
| 30 | + an addition from the second rolling (1-6). |
| 31 | + If the first outcome is (known) 3, then the probability of |
| 32 | + getting each of 4 to 9 will be 1/6. |
| 33 | + |
| 34 | + The sum becomes 2 for two 1 outcomes. But the sum becomes |
| 35 | + 3 for two outcomes (1,2) and (2,1). |
| 36 | + |
| 37 | + Link: |
| 38 | + https://www.thoughtco.com/probabilities-of-rolling-two-dice-3126559 |
| 39 | + |
| 40 | + That phenomenon is the same as the convolution. However, the index |
| 41 | + position is different. Therefore, we adjust the index. |
| 42 | + |
| 43 | + |
| 44 | + NB: a) We are assuming a fair dice |
| 45 | + b) Bernoulli's theory works with getting the probability of |
| 46 | + exactly 3 sixes while rolling 5 times. It does not work directly |
| 47 | + with the sum. The same sum can come in many combinations. |
| 48 | + Finding all of those combinations and applying Bernoulli |
| 49 | + is more computationally extensive. |
| 50 | + c) The algorithm can be used in playing games where the sum of |
| 51 | + multiple dice throwing is needed. |
| 52 | + |
| 53 | + I used that method in my paper to draw the distribution |
| 54 | + Titled: Uncertainty-aware Decisions in Cloud Computing: |
| 55 | + Foundations and Future Directions |
| 56 | + Journal: ACM Computing Surveys (CSUR) |
| 57 | + link: https://dl.acm.org/doi/abs/10.1145/3447583 |
| 58 | + The PDF version of the paper is available on Google Scholar. |
| 59 | +
|
| 60 | +
|
| 61 | + >>> import numpy as np |
| 62 | + >>> outcome_of_rolling_n_sided_dice_k_time(.2,.5) |
| 63 | + Traceback (most recent call last): |
| 64 | + ... |
| 65 | + ValueError: The function only accepts integer values |
| 66 | + >>> outcome_of_rolling_n_sided_dice_k_time(-1,5) |
| 67 | + Traceback (most recent call last): |
| 68 | + ... |
| 69 | + ValueError: Side count should be more than 1 |
| 70 | + >>> outcome_of_rolling_n_sided_dice_k_time(3,-2) |
| 71 | + Traceback (most recent call last): |
| 72 | + ... |
| 73 | + ValueError: Roll count should be more than 0 |
| 74 | +
|
| 75 | + >>> outcome_of_rolling_n_sided_dice_k_time(4,2) |
| 76 | + [range(2, 9), |
| 77 | + array([0.0625, 0.125 , 0.1875, 0.25 , 0.1875, 0.125 , 0.0625])] |
| 78 | + >>> outcome_of_rolling_n_sided_dice_k_time(6,2) |
| 79 | + [range(2, 13), |
| 80 | + array([0.02777778, 0.05555556, 0.08333333, 0.11111111, 0.13888889, |
| 81 | + 0.16666667, 0.13888889, 0.11111111, 0.08333333, 0.05555556, |
| 82 | + 0.02777778])] |
| 83 | + >>> outcome_of_rolling_n_sided_dice_k_time(6,3) |
| 84 | + [range(3, 19), |
| 85 | + array([0.00462963, 0.01388889, 0.02777778, 0.0462963 , 0.06944444, |
| 86 | + 0.09722222, 0.11574074, 0.125 , 0.125 , 0.11574074, |
| 87 | + 0.09722222, 0.06944444, 0.0462963 , 0.02777778, 0.01388889, |
| 88 | + 0.00462963])] |
| 89 | + """ |
| 90 | + |
| 91 | + if n_side != int(n_side) or k_time != int(k_time): |
| 92 | + raise ValueError("The function only accepts integer values") |
| 93 | + if n_side < 2: |
| 94 | + raise ValueError("Side count should be more than 1") |
| 95 | + if k_time < 1: |
| 96 | + raise ValueError("Roll count should be more than 0") |
| 97 | + if k_time > 100 or n_side > 100: |
| 98 | + raise ValueError("Limited to 100 sides or rolling to avoid memory issues") |
| 99 | + |
| 100 | + probability_distribution = 1 |
| 101 | + distribution_step = np.ones(n_side)/n_side |
| 102 | + |
| 103 | + iter1 = 0 |
| 104 | + while iter1 < k_time: |
| 105 | + probability_distribution =np.convolve(probability_distribution, distribution_step) |
| 106 | + iter1 = iter1+1 |
| 107 | + |
| 108 | + output = [] |
| 109 | + index = range(k_time,k_time*n_side+1) |
| 110 | + output.append(index) |
| 111 | + output.append(probability_distribution) |
| 112 | + return output |
| 113 | + |
| 114 | + |
| 115 | +''' |
| 116 | +# Extra code for the verification |
| 117 | +
|
| 118 | +index_dist = outcome_of_rolling_n_sided_dice_k_time(6, 5) |
| 119 | +
|
| 120 | +print("Indexes:",index_dist[0]) |
| 121 | +print("Distribution:",index_dist[1], "Their summation:",np.sum(index_dist[1])) |
| 122 | +
|
| 123 | +import matplotlib.pyplot as plt |
| 124 | +plt.bar(index_dist[0], index_dist[1]) |
| 125 | +
|
| 126 | +''' |
0 commit comments