No AnyDice, como posso calcular o número de sucessos no dado mais alto em um dado conjunto de dados?

4

Eu tentei o seguinte código

saída [contagem {5..6} em [o mais alto 2 de 10d6]]

Qual produz

0: 99.90% 1: 0.10%

No entanto, esses resultados são implausíveis. Em um pool 10d6, as chances de haver pelo menos um 6 ou 5 devem ser extremamente altas e duas delas devem ser esperadas pelo menos de vez em quando.


Agora entendo que o AnyDice está tentando encontrar 5s e 6s no diretório soma dos dois primeiros dados da piscina, o que não é o que eu quero. Ainda não estou perto de descobrir como conseguir o que estou procurando.

por Miguel Bartelsman 02.11.2018 / 22:35

3 respostas

Como A_S00 já observou, seu problema é que a função AnyDice interna [maior número de dados] retorna o soma dos dados mais altos na piscina.

De fato, dentro das restrições do modelo de dados do AnyDice, é tudo o que pode Faz. AnyDice pode lidar apenas com os seguintes tipos de variáveis:

  • números inteiros únicos ("números"),
  • listas finitas de números inteiros ("sequências"),
  • distribuições de probabilidade sobre conjuntos finitos de números inteiros ("dados" únicos) e
  • "pools" de dois ou mais dados idênticos (!) ("coleções de dados").

(Na verdade, o AnyDice não faz diferença real entre os dois últimos tipos listados acima; um único dado é tratado exatamente como uma coleção de um dado. Mas, conceitualmente, pode ser útil diferenciá-los.)

Notavelmente, uma variável AnyDice não podes armazena uma distribuição de probabilidade por seqüências, nem pode armazenar uma coleção ou sequência de vários tipos diferentes de dados. Portanto, não há realmente nenhuma maneira prática para o AnyDice representar, por exemplo, "os números mais altos do 2 agrupados com o 10d6" sem, de alguma forma, colapsá-lo em um desses tipos suportados.

Claro, não seria difícil escrever uma função AnyDice que pega uma sequência e retorna outra sequência contendo os dois (ou qualquer número de) números mais altos nela. De fato, aqui está um, apenas como exemplo:

function: highest NUMBER:n of sequence SEQUENCE:s {
  SORTED: [sort SEQUENCE]  \ could be skipped if SEQUENCE known to be already sorted \
  R: {}
  loop P over {1..NUMBER} { R: {R, [email protected]} }
  result: R
}

E isso realmente funcionará bem, desde que você o use apenas em sequências normais e não aleatórias. Por exemplo, [2 mais alto da sequência {3,2,1}] realmente retornará a sequência 3,2 {}. Mas se você tentar aplicá-lo a uma coleção de dados, tudo o que obterá é o soma dos resultados mais altos, exatamente o mesmo que você obteria com o [maior número de dados] função.

Isso acontece porque, sempre que você tentar passar uma coleção de dados para uma função que espera uma sequência, o AnyDice invocará a função para cada resultado possível de rolar os dados e coletará os resultados em um dado personalizado (ou seja, uma distribuição de probabilidade) em que a probabilidade de cada resultado é a probabilidade total de todos os rolos que produzem esse resultado. Mas, como observei acima, o AnyDice pode lidar apenas com distribuições de probabilidade com valor inteiro; um dado no AnyDice não pode ter um lado chamado "{3, 2}". Portanto, se algum dos resultados retornados pela função forem sequências em vez de números únicos, o AnyDice deve transformá-los em números - e a maneira como isso acontece, por padrão, é somando os números na sequência.


O padrão e, realmente, a única maneira de contornar essa limitação é fazer o que você quiser com a sequência de resultados dentro a função, antes de devolvê-la. Por exemplo, assim:

function: count VALUES:s in highest NUMBER:n of ROLL:s {
  R: {}
  loop P over {1..NUMBER} { R: {R, [email protected]} }
  result: [count VALUES in R]  \ here, R is still a sequence \
}

output [count {5..6} in highest 2 of 10d6]

(Aqui eu pulei a classificação ROLO sequência, já que as sequências geradas pelo AnyDice repetindo os possíveis resultados de uma rolagem de dados já estão classificadas de qualquer maneira.)

Também é muito fácil generalizar essa função para permitir a seleção qualquer posições nos rolos classificados a serem contados, por exemplo como isso:

function: count VALUES:s in positions POSITIONS:s of ROLL:s {
  R: {}
  loop P over POSITIONS { R: {R, [email protected]} }
  result: [count VALUES in R]
}

output [count {5..6} in positions {1..2} of 10d6] named "count 5..6 in highest two of 10d6"
output [count {5..6} in positions {3..4} of 10d6] named "count 5..6 in 2nd highest two of 10d6"
output [count {5..6} in positions {5..6} of 10d6] named "count 5..6 in middle two of 10d6"
output [count {5..6} in positions {7..8} of 10d6] named "count 5..6 in 2nd lowest two of 10d6"
output [count {5..6} in positions {9..10} of 10d6] named "count 5..6 in lowest two of 10d6"

Termo aditivo: No caso particular de contar dados que rolam acima um determinado limiar entre os \ $ N \ $ mais dados na piscina, existem maneiras muito mais simples de obter o mesmo resultado. O principal insight é que, se você rolar algum dado acima do limite, eles sempre estarão entre os \ $ N \ $ mais alto - a menos que, se for claro, você rolar mais de \ $ N \ $ dados acima do limite, caso em que você terá algumas sobras.

Assim, em particular, as duas linhas seguintes produzir exatamente a mesma saída:

output [count {5..6} no mais alto 2 de 10d6] output [mais baixo de 2 e [count {5..6} em 10d6]]

Obviamente, você nem precisa limitar os resultados a, no máximo, 2 no código - você também pode deixar o AnyDice traçar toda a distribuição of [conte {5..6} em 10d6] e basta olhar para as duas primeiras colunas.

De fato, você também pode usar o último duas colunas do mesmo gráfico para obter a distribuição de 5s e 6s entre os menor dois dados no 10d6 e, com algum cuidado, você também pode fazer o mesmo nos intervalos intermediários. Ou você pode apenas deixe AnyDice fazer as contas para você:

function: middle of A:n and B:n and C:n {
  result: [email protected][sort {A, B, C}]
}

output [middle of 0 and [count {5..6} in 10d6] - 0 and 2] named "count 5..6 in highest two of 10d6"
output [middle of 0 and [count {5..6} in 10d6] - 2 and 2] named "count 5..6 in 2nd highest two of 10d6"
output [middle of 0 and [count {5..6} in 10d6] - 4 and 2] named "count 5..6 in middle two of 10d6"
output [middle of 0 and [count {5..6} in 10d6] - 6 and 2] named "count 5..6 in 2nd lowest two of 10d6"
output [middle of 0 and [count {5..6} in 10d6] - 8 and 2] named "count 5..6 in lowest two of 10d6"

Para otimizar ainda mais, poderíamos usar o "truque de remarcação" e crie um d6 personalizado com os lados 1-4 renumerados como 0 e os lados 5-6 como 1. Isso não apenas evita que o AnyDice precise repetir vários rolos diferentes, mas equivalentes, mas como agora estamos apenas contando os lados renumerados como 1, nem precisamos chamar nenhuma função explícita para isso - apenas deixando o AnyDice implicitamente somar os resultados do rolo são suficientes.

Com essa otimização, o código acima pode ser escrito de forma equivalente como isso:

HIT: d6> = 5 \ renomeia os lados 1..4 para 0 e 5..6 para 1 \ saída [no meio de 0 e 10dHIT - 0 e 2] denominada "conta 5..6 nas duas saídas mais altas de 10d6" [ meio do 0 e 10dHIT - 2 e 2] nomeado "conte 5..6 no 2 e o mais alto dos dois resultados do 10d6" [meio do 0 e 10dHIT - 4 e 2] chamado "conte o número 5..6 no meio do resultado do 10d6" [meio do 0 e 10dHIT - 6 e 2] nomeado "conte 5..6 no 2 e os dois mais baixos da saída 10d6" [meio do 0 e 10dHIT - 8 e 2] chamado "conte 5..6 nos dois mais baixos do 10d6"

Obviamente, esses dois truques são um tanto limitantes, pois não funcionariam (sem modificações apropriadas) se quiséssemos contar, digamos, o número de uns e dois (ou mesmo, digamos, uns e três e cinco) entre os mais alto (ou mais baixo, ou meio, etc.) dois de 10d6. Mas quando eles funcionam, eles podem ser muito úteis.

03.11.2018 / 07:04

Como você supôs, a fórmula que você está usando está fornecendo a contagem de quantas vezes o soma de [o mais alto 2 de 10d6] é 5 ou 6. Escusado será dizer que isso é extremamente raro, uma vez que rolar os dados 10 quase sempre fará com que os rolos 2 sejam altos o suficiente para somar a 7 ou mais.

Não conheço uma maneira elegante de obter a função "mais alta" incorporada para fornecer uma seqüência dos dados mais altos, em vez dos soma desses dados mais altos ... então aqui está uma totalmente deselegante maneira de fazer isso:

função: truncar A: n a dois {se A> 2 {resultado: 2} resultado: A} saída [truncar ((d6> = 5) + (d6> = 5) + (d6> = 5) + (d6> = 5) + (d6> = 5) + (d6> = 5) + (d6> = 5) + (d6> = 5) + (d6> = 5) + (d6> = 5) para dois]

Experimente aqui!

O que isso faz é:

  • Rola 1d6 dez vezes, independentemente.
  • Para cada um, verifica se o resultado é maior ou igual a 5 (ou seja, se for um sucesso), retornando 1 se é um sucesso e 0 se não.
  • Soma os resultados (como retornamos o 1 com sucesso e o 0 com falha, o soma dos resultados é o mesmo que o contar de sucessos).
  • Passa a soma por meio de uma função definida pelo usuário que arredonda o total para 2, se for maior que 2. Isso equivale a tirar o melhor 2 do 10.

Eu não ficaria surpreso se houvesse uma maneira menos exigente de conseguir isso, mas isso faz o que você deseja. Os resultados são:

  • 1.73% chance de sucessos do 0
  • 8.67% chance de sucesso do 1
  • 89.60% chance de sucessos do 2
02.11.2018 / 23:23

Pense no problema, não nos dados físicos. Qualquer dado não está restrito a usar dados "reais".

Um sucesso acontece \ $ 1 \ sobre 3 \ $ vezes, para que você não queira um d6, você quer um {0,0,1}.

Em seguida, jogue este dado:

saída [o mais alto 2 do 10d {0,0,1}]

e você terá uma probabilidade de sucessos 0, 1, 2.

03.11.2018 / 01:23

Tags