Advertisement
Guest User

Dice rolls stats

a guest
May 7th, 2025
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.87 KB | Source Code | 0 0
  1. def v1():
  2.     "Your original version"
  3.    
  4.     i = j = k = l = m = n = 1
  5.     total = maximumRolls = 0
  6.     while i < 7:
  7.         while j < 7:
  8.             while k < 7:
  9.                 while l < 7:
  10.                     values = [i, j, k, l]
  11.                     values.sort()
  12.                     subtotal = values[1] + values[2] + values[3]
  13.                     total += subtotal
  14.                     if subtotal == 18:
  15.                         maximumRolls += 1
  16.                     l += 1
  17.                 k += 1
  18.                 l = 1
  19.             j += 1
  20.             k = 1
  21.         i += 1
  22.         j = 1
  23.    
  24.     total = total / 1296
  25.    
  26.     print("Average of 4d6kh3 = " + str(total)[:5] + " Max Rolls: " + str(maximumRolls) + "/1296 (" + str(maximumRolls * 100 / 1296)[:4] + "%)")
  27.  
  28.  
  29.  
  30. from itertools import product
  31. def v2(num_dice, faces_per_die, num_highest_to_keep):
  32.     "itertools.product to generate all the possible rolls"
  33.    
  34.     max_roll_count = total_sum = 0
  35.     total_combinations = faces_per_die ** num_dice
  36.  
  37.     for roll in product(range(1, faces_per_die + 1), repeat=num_dice):
  38.         sorted_roll = sorted(roll, reverse=True)
  39.         kept_sum = sum(sorted_roll[:num_highest_to_keep])
  40.         total_sum += kept_sum
  41.  
  42.         if kept_sum == num_highest_to_keep * faces_per_die:
  43.             max_roll_count += 1
  44.  
  45.     average = total_sum / total_combinations
  46.     percentage = (max_roll_count / total_combinations) * 100
  47.  
  48.     print(f"Average of {num_dice}d{faces_per_die}kh{num_highest_to_keep} = {average:.2f} "
  49.           f"Max Rolls: {max_roll_count}/{total_combinations} ({percentage:.2f}%)")
  50.    
  51. import numpy as np
  52.  
  53. def v3(num_dice, faces_per_die, num_highest_to_keep):
  54.     """Recursively generating the the rolls, we start at the top with no roll
  55.    and we go further adding one roll value in the roll at a time,
  56.    when n==0 we are at the bottom layer of the recursion and we have our complete roll with n num_dice values
  57.    and we propagate the 2 values we care about to the top : total_sum and max_roll_count
  58.    by doing the sum of all the n-1 layers values until we are back to the top
  59.    """
  60.     def v3_rec(n, roll):
  61.         if n == 0:
  62.             sorted_roll = sorted(roll, reverse=True)
  63.             kept_sum = sum(sorted_roll[:num_highest_to_keep])
  64.             max_roll = 1 if kept_sum == num_highest_to_keep * faces_per_die else 0
  65.             return [kept_sum, max_roll]
  66.        
  67.         return np.array([v3_rec(n-1, roll+[i]) for i in range(1, faces_per_die+1)]).sum(axis=0)
  68.    
  69.     total_sum, max_roll_count = v3_rec(num_dice, [])
  70.     total_combinations = faces_per_die ** num_dice
  71.    
  72.     average = total_sum / total_combinations
  73.     percentage = (max_roll_count / total_combinations) * 100
  74.    
  75.     print(f"Average of {num_dice}d{faces_per_die}kh{num_highest_to_keep} = {average:.2f} "
  76.           f"Max Rolls: {max_roll_count}/{total_combinations} ({percentage:.2f}%)")
  77.    
  78.  
  79. def v4(num_dice, faces_per_die, num_highest_to_keep):
  80.     """From a roll we generate a new roll, for example with 4d6, if we are at [1,1,1,1] the
  81.    next roll is [1,1,1,2], and if we are at [1,1,1,6] the next one is [1,1,2,1]
  82.    and once we are at [6,6,6,6] then we know its finished
  83.    """
  84.     max_roll_count = total_sum = 0
  85.     total_combinations = faces_per_die ** num_dice
  86.  
  87.     roll = [1 for _ in range(num_dice)]
  88.     returned_to_start = False
  89.     while not returned_to_start:
  90.         sorted_roll = sorted(roll, reverse=True)
  91.         kept_sum = sum(sorted_roll[:num_highest_to_keep])
  92.         total_sum += kept_sum
  93.         if kept_sum == num_highest_to_keep * faces_per_die:
  94.             max_roll_count += 1
  95.        
  96.         carry_the_addition = True
  97.         idx = num_dice-1
  98.        
  99.         while carry_the_addition:
  100.             if roll[idx] + 1 > faces_per_die:
  101.                 if idx == 0:
  102.                     returned_to_start = True
  103.                     break
  104.                
  105.                 roll[idx] = 1
  106.                 idx -= 1
  107.             else:
  108.                 roll[idx] += 1
  109.                 carry_the_addition = False
  110.    
  111.     average = total_sum / total_combinations
  112.     percentage = (max_roll_count / total_combinations) * 100
  113.    
  114.     print(f"Average of {num_dice}d{faces_per_die}kh{num_highest_to_keep} = {average:.2f} "
  115.           f"Max Rolls: {max_roll_count}/{total_combinations} ({percentage:.2f}%)")
  116.    
  117. def v5(num_dice, faces_per_die, num_highest_to_keep):
  118.     """Same as v4 but with for example 4d6, the rolls are from 0 to 5 when doing
  119.    next roll calculations so we can use % and // operators more easily,
  120.    to get the true roll we just add 1 to every value of the roll
  121.    """
  122.    
  123.     max_roll_count = total_sum = 0
  124.     total_combinations = faces_per_die ** num_dice
  125.     for i in range(total_combinations):
  126.         roll_minus_one = []
  127.         temp = i
  128.         for _ in range(num_dice):
  129.             roll_minus_one.append(temp % faces_per_die)
  130.             temp //= faces_per_die
  131.        
  132.         roll = [v+1 for v in roll_minus_one]
  133.         sorted_roll = sorted(roll, reverse=True)
  134.        
  135.         kept_sum = sum(sorted_roll[:num_highest_to_keep])
  136.         total_sum += kept_sum
  137.         if kept_sum == num_highest_to_keep * faces_per_die:
  138.             max_roll_count += 1
  139.    
  140.     average = total_sum / total_combinations
  141.     percentage = (max_roll_count / total_combinations) * 100
  142.     print(f"Average of {num_dice}d{faces_per_die}kh{num_highest_to_keep} = {average:.2f} "
  143.           f"Max Rolls: {max_roll_count}/{total_combinations} ({percentage:.2f}%)")
  144.            
  145.  
  146. def v6(num_dice, faces_per_die):
  147.     """I asked the LLM o4-mini to come up with a mathematical formula to compute things
  148.    i asked the formula for the special case when we take the highest n-1 die because its easier to compute
  149.    Because in this case the expectancy of the n-1 highest dice is the expetancy of the n dice
  150.    minus the expectancy of the min value of the n dice.
  151.    Function generated by o4-mini
  152.    """
  153.     num_highest_to_keep = num_dice - 1
  154.     n, f = num_dice, faces_per_die
  155.    
  156.     # 1) E[min of n dice] = sum_{k=1}^f P(min >= k)
  157.     #                  = sum_{k=1}^f ((f+1-k)/f)^n
  158.     E_min = sum(((f + 1 - k) / f) ** n for k in range(1, f + 1))
  159.  
  160.     # 2) E[sum of all n dice] = n * (f+1)/2
  161.     #    so E[sum of top n-1] = n*(f+1)/2 - E_min
  162.     average = n * (f + 1) / 2 - E_min
  163.  
  164.     # 3) P(max roll) occurs if at least n-1 dice = f
  165.     #    = C(n,n-1)*(1/f)^(n-1)*((f-1)/f) + (1/f)^n
  166.     #    = (n*(f-1) + 1) / f^n
  167.     p_max = (n * (f - 1) + 1) / (f**n)
  168.    
  169.     print(f"Expectancy of {num_dice}d{faces_per_die}kh{num_highest_to_keep} = {average:.2f} "
  170.           f"Max Rolls expectancy : {p_max*100:.2f}%")
  171.  
  172.  
  173.  
  174.  
  175. nb_dices = 4
  176. nb_dice_faces = 6
  177. top_n = 3
  178.  
  179. v1()
  180. v2(nb_dices, nb_dice_faces, top_n)
  181. v3(nb_dices, nb_dice_faces, top_n)
  182. v4(nb_dices, nb_dice_faces, top_n)
  183. v5(nb_dices, nb_dice_faces, top_n)
  184. v6(nb_dices, nb_dice_faces)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement