Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Sadly one of the "not a python but math" missions solution in Clear category for Probably Dice by Mysta
from typing import List
# -----------------------------------------------------------------------------
def count_combinations(dice_number: int, sides: int, target: int):
# This function is not written by myself but is an adaption and
# optimisation I've done after analysing the algorithm of some code
# snippets found on the internet. That may be seen as a little bit
# cheating, but to be honest: Do we here learn python programming or
# solving math problems?
# Create a table for counting the possibilities to achieve with d dices
# a target t. In the end dt[d][t] contains the number of possibilities
# to achieve the target sum t with d dices
dt: List[List[int]] = [[0] * (target + 1) for _ in range(dice_number + 1)]
# There is only one possibility to achieve target 0 with 0 dices!
dt[0][0] = 1
for d in range(1, dice_number + 1): # used number of dices
for t in range(1, target + 1): # target sum (<= target)
for face in range(1, min(t, sides) + 1): # dice values
# For the current number of dices and the current target the
# number of possibilities has to be increased by the number of
# possibilities getting the target t without the current dice
# value when one dice less is used
dt[d][t] += dt[d - 1][t - face]
# Finally the table entry at the bottom right contains the number of
# combinations to achieve the target with the given number of dices
return dt[dice_number][target]
# -----------------------------------------------------------------------------
def probability(dice_number: int, sides: int, target: int) -> float:
# Get the number of possible combinations the dice roll result is the
# desired target value
target_combinations: int = count_combinations(dice_number, sides, target)
# Get the total number of possible results a dice roll may have
possible_results: int = sides**dice_number
# Calculate the probability of getting a total roll of exactly the
# target value
return target_combinations / possible_results
# -----------------------------------------------------------------------------
if __name__ == '__main__':
#These are only used for self-checking and are not necessary for auto-testing
def almost_equal(checked, correct, significant_digits=4):
precision = 0.1 ** significant_digits
return correct - precision < checked < correct + precision
assert(almost_equal(probability(2, 6, 3), 0.0556)), "Basic example"
assert(almost_equal(probability(2, 6, 4), 0.0833)), "More points"
assert(almost_equal(probability(2, 6, 7), 0.1667)), "Maximum for two 6-sided dice"
assert(almost_equal(probability(2, 3, 5), 0.2222)), "Small dice"
assert(almost_equal(probability(2, 3, 7), 0.0000)), "Never!"
assert(almost_equal(probability(3, 6, 7), 0.0694)), "Three dice"
assert(almost_equal(probability(10, 10, 50), 0.0375)), "Many dice, many sides"
Jan. 28, 2026