Meu capítulo local da ACM oferece prêmios para as pessoas que comparecem às reuniões. Você tem uma chance maior de ganhar se resolver o quebra-cabeça de programação, no entanto (mas eu sempre resolvo esse quebra-cabeça). Assim, algumas pessoas têm 1 entrada, enquanto outras têm 2. Mas espere! A maneira como o programa de sorteio funciona não é adicionando outra entrada quando alguém resolve o quebra-cabeça. Em vez disso, ele controla o número de "vidas" que uma pessoa tem, diminuindo que, se essa pessoa for escolhida em cada passagem do seu algoritmo de amostragem aleatória. Então, funciona assim:
Doorknob: 1. xnor: 2. Justin: 2. Alex: 1. Dennis: 2.
Em seguida, o programa escolhe aleatoriamente um dos [Doorknob, xnor, Justin, Alex, Dennis]
, diminui o número (diga que ele escolhe Justin
):
Doorknob: 1. xnor: 2. Justin: 1. Alex: 1. Dennis: 2.
E repete. Se o número de "vidas" de alguém for para 0
(vamos escolher Justin
novamente), eles serão removidos da lista:
Doorknob: 1. xnor: 2. Alex: 1. Dennis: 2.
Isso continua até que haja uma pessoa; essa pessoa é a vencedora.
Agora, a verdadeira questão é: qual era a probabilidade de ganhar?
Você receberá duas entradas:
n
. Este é o número de pessoas que participaram do desafiok
. Este é o número de pessoas (daquelasn
) que têm 2 vidas. Esse número sempre inclui você.
Então, se eu tivesse uma função p
e telefonasse p(10, 5)
, essa seria a probabilidade de ganhar o prêmio onde há 10 pessoas no total, 5 das quais têm apenas 1 vida, enquanto 5 (incluindo você) têm 2 vidas.
Espera-se que você produza a probabilidade de ganhar exatamente ou como um decimal. De qualquer forma, as respostas devem ser até precisos e incluindo a 4 ª casa decimal depois do ponto decimal. Você deve ou não arredondar para esse dígito.
Sua solução pode ser uma solução randomizado que gera a resposta para a 4 ª casa decimal com alta probabilidade . Você pode supor que o RNG incorporado que você usa é verdadeiramente aleatório e deve gerar a resposta correta com pelo menos 90% de probabilidade.
Além disso, seu código precisa apenas funcionar n, k <= 1000
, embora eu tenha fornecido casos de teste maiores que os para aqueles curiosos.
Casos de teste
Nota: algumas dessas são fórmulas gerais.
n, k | output
----------+---------
1, 1 | 1
2, 2 | 0.5
2, 1 | 0.75
3, 1 | 11/18 = 0.611111111
1000, 1 | 0.007485470860550352
4, 3 | 0.3052662037037037
k, k | 1/k
n, 1 | (EulerGamma + PolyGamma[1 + n])/n (* Mathematica code *)
| (γ + ψ(1 + n))/n
10, 6 | 0.14424629234373537
300, 100 | 0.007871966408910648
500, 200 | 0.004218184180294532
1000, 500 | 0.0018008560286627948
---------------------------------- Extra (not needed to be a valid answer)
5000, 601 | 0.0009518052922680399
5000, 901 | 0.0007632938197806958
Para mais algumas verificações, faça p(n, 1) * n
o seguinte:
n | output
------+---------
1 | 1
2 | 1.5
3 | 1.8333333333333335
10 | 2.928968253968254
100 | 5.1873775176396215
-------------------------- Extra (not needed to be a valid answer)
100000| 12.090146129863305
fonte
k
está fora por um)Respostas:
MATL , 42 bytes
Isso usa uma abordagem probabilística (Monte Carlo). O experimento é realizado um grande número de vezes, a partir do qual a probabilidade é estimada. O número de realizações é selecionado para garantir que o resultado esteja correto até a quarta casa decimal com probabilidade de pelo menos 90%. No entanto, isso leva muito tempo e muita memória. No link abaixo, o número de realizações foi reduzido em um fator de 10 6, para que o programa termine em um período razoável de tempo; e apenas a primeira casa decimal é garantida como precisa com pelo menos 90% de probabilidade.
EDIT (29 de julho de 2016): devido a alterações no idioma,
6L
precisa ser substituído por3L
. O link abaixo incorpora essa modificação.Experimente online!
fundo
Vamos p denotar a probabilidade de ser computada. O experimento descrito no desafio vai ser executado por um número n de vezes. Cada vez, você ganha o prêmio (" sucesso ") ou não. Seja N o número de sucessos. A probabilidade desejada pode ser estimada a partir de N e n . Quanto maior n for, mais precisa será a estimativa. A questão principal é como selecionar n para cumprir com a precisão desejada, ou seja, garantir que pelo menos 90% das vezes o erro seja menor que 10 -4 .
Os métodos de Monte Carlo podem ser
Entre a segunda categoria, um método comum usado é fixar N (número desejado de sucessos) e continuar simulando até que esse número seja alcançado . Assim, n é aleatório. Essa técnica, chamada amostragem binomial inversa ou Monte Carlo binomial negativo , tem a vantagem de que a precisão do estimador pode ser limitada. Por esse motivo, será usado aqui.
Especificamente, com Monte Carlo binomial negativo x = ( N −1) / ( n −1) é um estimador imparcial de p ; e a probabilidade de que x se desvie de p em mais de uma dada razão pode ser superior. De acordo com a equação (1) deste artigo (observe também que as condições (2) são satisfeitas), tomar N = 2,75 · 10 8 ou maior garante que p / x pertence ao intervalo [1.0001, 0,9999] com pelo menos 90% probabilidade. Em particular, isso implica que x está correto até a quarta casa decimal com pelo menos 90% de probabilidade, conforme desejado.
Código explicado
O código usa N =
3e8
para salvar um byte. Observe que fazer muitas simulações levaria muito tempo. O código no link usa N =300
, que é executado em um período de tempo mais razoável (menos de 1 minuto no compilador online para os primeiros casos de teste); mas isso apenas garante que o primeiro decimal esteja correto com probabilidade de pelo menos 90%.fonte
Pitão, 34 bytes
Suíte de teste
Define uma função recursiva memorizada determinística,
g
tomando n , k como argumentos.g 1000 500
retorna0.0018008560286627952
em cerca de 18 segundos (não incluído no conjunto de testes acima, pois o tempo excede o intérprete online).Uma tradução aproximada do Python 3 seria
fonte
JavaScript (ES6), 65 bytes
Não tente com os grandes números; até f (30, 10) leva um tempo notável.
fonte