Aqui está uma rotina Python mais rápida que fornece resultados exatos (até os limites de precisão numérica, de qualquer forma):
# Target number and initial bonus + headway:
target = 10
bonus = 1
headway = 0
# Die sizes:
attempt_die = 10 # 1d10
headway_die = 3 # 1d3
# print header:
print "target: {0}, bonus {1:+d}, initial headway {2}".format(
target, bonus, headway)
print "rolling 1d{0} for success, 1d{1} for headway".format(
attempt_die, headway_die)
# initial headway distribution:
distribution = [0.0] * (max(target - bonus, headway) + 1)
distribution[headway] = 1.0
def clamp(probability):
return min(1, max(0, probability))
cumulative = 0.0 # total success probability so far
expected = 0.0 # expected number of attempts needed
for attempt in xrange(1, 1 + max(1, target - bonus - headway)):
success = 0.0 # total success probability for this attempt
# loop through possible current headway values (in reversed order,
# to avoid having to copy the distribution list):
for curr_hw in reversed(xrange(len(distribution))):
headway_prob = distribution[curr_hw]
if headway_prob == 0: continue
# probability of rolling below the target:
failure_prob = clamp(float(target - bonus - curr_hw - 1) / attempt_die)
success += headway_prob * (1 - failure_prob)
# if the initial roll fails, increment headway (if headway exceeds
# target - bonus, set it to that value so that next roll will
# automatically succeed):
distribution[curr_hw] = 0
for roll in xrange(1, 1 + headway_die):
new_hw = min(curr_hw + roll, len(distribution) - 1)
distribution[new_hw] += failure_prob * headway_prob / headway_die
cumulative += success
expected += success * attempt
print "success on attempt {0:2d}:".format(attempt), \
"{0:9.5f}%".format(success * 100), \
"(cumulative {0:9.5f}%)".format(cumulative * 100)
# print "headway:", ", ".join(
# "{0}: {1:g}%".format(hw, 100 * distribution[hw]) \
# for hw in range(len(distribution))
# )
print "expected number of attempts needed =", expected
Aqui está a saída para target = 10
, bonus = 1
e headway = 0
:
target: 10, bonus +1, initial headway 0
rolling 1d10 for success, 1d3 for headway
success on attempt 1: 20.00000% (cumulative 20.00000%)
success on attempt 2: 32.00000% (cumulative 52.00000%)
success on attempt 3: 28.26667% (cumulative 80.26667%)
success on attempt 4: 14.90370% (cumulative 95.17037%)
success on attempt 5: 4.19664% (cumulative 99.36701%)
success on attempt 6: 0.58975% (cumulative 99.95677%)
success on attempt 7: 0.04180% (cumulative 99.99857%)
success on attempt 8: 0.00142% (cumulative 99.99998%)
success on attempt 9: 0.00002% (cumulative 100.00000%)
expected number of attempts needed = 2.53240636049
Esse código funciona mantendo as probabilidades de todos os possíveis valores de headway atuais no array distribution
e atualizando-os com base nas probabilidades dos vários resultados possíveis dos testes de dados.
Se desejar, o código acima pode ser feito para gerar a distribuição de diferentes valores de headway após cada tentativa, descomprometendo a instrução print
extra no final do loop externo.
(Note que esta não é, estritamente falando, uma distribuição de probabilidade adequada, pois não inclui a probabilidade de que o treinamento já tenha sido bem sucedido. Assim, para tentativas posteriores, as probabilidades de headway somarão um valor estritamente menor que 100%, embora adicionando a probabilidade de sucesso cumulativo irá corrigir isso.)