Probabilidades de nocaute

9

Nocaute é um jogo de basquete, onde os jogadores se revezam atirando. É jogado como uma sequência de competições para dois jogadores, cada um com a possibilidade de "nocautear" um desses jogadores.

Suponha que os jogadores sejam A B C De suas chances de arremessar e fazer uma cesta sejam 0.1 0.2 0.3 0.4respectivamente, independentemente do outro jogador na competição. Os dois jogadores na frente da fila Ae B"brigam". Desde que Avai primeiro, ele é o defensor , em risco de ser eliminado, e Bé o atacante , e não em risco de eliminação imediata. Aatira primeiro. Se Afaz, Adefendeu com sucesso, e vai para o fim da linha. A linha mudaria para B C D A. Se Anão conseguir, então Batira. Se o Bfizer, Asai e Bvai para o fim da linha, para que a linha se torne C D B. Se nemAnem o Bfaz, o processo se repete, com o Adisparo novamente, até que um Aou Bfaça uma cesta.

Suponha que a linha tenha sido alterada para B C D A( Ahavia sido defendida com sucesso). Agora, Be C"lute", Bsendo o defensor e Co atacante. Esse processo se repete até restar apenas uma pessoa. Essa pessoa é a vencedora.

Sua tarefa é calcular as probabilidades de cada pessoa ganhar, tendo a chance de fazer uma cesta.

Entrada :

Uma lista de números, como 0.1 0.2ou 0.5 0.5 0.5 0.5, onde o n º número é a chance de que o n º jogador irá fazer uma cesta. Você pode levar essa entrada em qualquer formato que desejar, incluindo os parâmetros para uma função.

Saída :

Uma lista de números, onde o n º número é a chance de que o n º jogador vai ganhar o jogo. Seus números devem ter precisão de pelo menos duas casas decimais em pelo menos 90% das vezes. Isso significa que você pode usar uma abordagem baseada em simulação. No entanto, se o seu código não for baseado em simulação (é garantido que você retorne uma resposta correta com pelo menos 6 casas decimais), retire 30% da sua pontuação.

Exemplo entre 0.5 0.5: Ligue para os jogadores Ae B. Let pSer a probabilidade de A ganhar. Atem uma 2/3chance de defender com sucesso (já que há uma 1/2chance de Amarcar, uma 1/4chance de Aerrar e Bmarcar e uma 1/4chance de errar e o processo se repetir). Se Anão se defender, ele é nocauteado e Bvence. Se Adefender, a linha se tornará B A. Como a situação é simétrica, a probabilidade de Avitória é (1 - p). Nós temos:

p = 2/3 * (1 - p) + 1/3 * 0. Resolvendo, chegamos p = 2/5. A saída deve ser 2/5 3/5ou 0.4 0.6.

Não sou bom o suficiente com probabilidade de fazer exemplos mais complexos.

Se você precisar de mais casos de teste, aqui estão alguns:

0.1 0.2 0.3 0.4 --> 0.01 0.12 0.25 0.62
0.99 0.99 --> 0.5 0.5 (it's not exact, but if you round to two decimal places, you get 0.5 and 0.5)
soktinpk
fonte

Respostas:

4

CJam ( 84 80 caracteres * 0,7 = 56)

{_,({_,,{_2$m<(;(+Q0\)\++m>\}%)_(+.{X2$-*_@+/}1\{1$*\1$-}%)1\-f/.f*:.+}{,da}?}:Q

Demonstração online . Esta é uma função recursiva que pega uma matriz de duplas e retorna uma matriz de duplas. A demonstração online inclui uma pequena quantidade de andaimes para executar a função e formatar a saída para exibição.

Dissecação

O princípio básico é que, se houver n > 1jogadores restantes, um deles deve ser o próximo a ser eliminado. Além disso, a ordem da fila depois que isso acontece depende apenas da ordem inicial da fila e de quem é eliminado. Assim, podemos fazer nchamadas recursivas, calcular as probabilidades de vitória de cada jogador em cada caso e, em seguida, basta ponderar adequadamente e adicionar.

Vou rotular as probabilidades de entrada como [p_0 p_1 ... p_{n-1}]. Vamos f(a,b)denotar a probabilidade de anão se defender b. Em qualquer rodada, a probabilidade de que adefende com sucesso é p_a, a probabilidade de que bbate afora é (1-p_a)*p_b, ea probabilidade de que ele vai para outra rodada é (1-p_a)*(1-p_b). Podemos fazer uma soma explícita de uma progressão geométrica ou argumentar que as duas progressões geométricas são proporcionais entre si para justificar isso f(a,b) = (1-p_a)*p_b / (p_a + (1-p_a)*p_b).

Então podemos subir um nível para rodadas completas da linha. A probabilidade de o primeiro jogador ser eliminado é f(0,1); a probabilidade de o segundo jogador ser eliminado é (1-f(0,1)) * f(1,2); o terceiro jogador é (1-f(0,1)) * (1-f(1,2)) * f(2,3); etc até que o último seja nocauteado com probabilidade \prod_i (1-f(i,i+1)) * f(n-1,0). O mesmo argumento sobre progressões geométricas nos permite usar essas probabilidades como pesos, com normalização por um fator de 1 / \prod_i f(i, i+1 mod n).

{                   e# Define a recursive function Q
  _,({              e# If we have more than one person left in the line...
    _,,{            e#   Map each i from 0 to n-1...
      _2$m<         e#     Rotate a copy of the probabilities left i times to get [p_i p_{i+1} ... p_{n-1} p_0 ... p_{i-1}]
      (;(+          e#     i fails to defend, leaving the line as [p_{i+2} ... p_{n-1} p_0 ... p_{i-1} p_{i+1}]
      Q             e#     Recursive call
      0\)\++        e#     Insert 0 for the probability of i winning and fix up the order
      m>\           e#     Rotate right i times and push under the list of probabilities
    }%
    )               e#   Stack: [probs if 0 knocked out, probs if 1 knocked out, ...] [p_0 p_1 ...]
    _(+.{           e#   Duplicate probs, rotate 1, and pointwise map block which calculates f(a,b)
      X2$-*_@+/     e#     f(a,b) = (1-p_a)*p_b / (p_a + (1-p_a)*p_b)  TODO is the d necessary?
    }
    1\{1$*\1$-}%    e#   Lift over the list of f(a,b) a cumulative product to get the weights  TODO is the d necessary?
    )1\-f/          e#   Normalise the weights
    .f*             e#   Pointwise map a multiplication of the probabilities for each case with the corresponding weight
    :.+             e#   Add the weights across the cases
  }{,da}?           e# ...else only one left, so return [1.0]
}:Q
Peter Taylor
fonte