Quelle est la chance que je gagne un prix de présence?

12

Ma section locale d'ACM remet des prix de présence aux personnes qui viennent aux réunions. Vous obtenez une chance accrue de gagner si vous résolvez le puzzle de programmation, cependant (mais je résous toujours ce puzzle). Ainsi, certaines personnes ont 1 entrée, tandis que d'autres en ont 2. Mais attendez! Le fonctionnement du programme de tombola n'est pas en ajoutant une autre entrée lorsque quelqu'un résout le puzzle. Au lieu de cela, il garde une trace du nombre de "vies" d'une personne, décrémentant que si cette personne est choisie à chaque passage de son algorithme d'échantillonnage aléatoire. Donc ça marche comme ça:

Doorknob: 1.  xnor: 2.  Justin: 2.  Alex: 1.  Dennis: 2.

Ensuite, le programme choisit au hasard l'un des [Doorknob, xnor, Justin, Alex, Dennis], décrémente le nombre (disons qu'il choisit Justin):

Doorknob: 1.  xnor: 2.  Justin: 1.  Alex: 1. Dennis: 2.

Et répète. Si le nombre de "vies" de quelqu'un va à 0(choisissons à Justinnouveau), il est supprimé de la liste:

Doorknob: 1.  xnor: 2.  Alex: 1.  Dennis: 2.

Cela continue jusqu'à ce qu'il reste une personne; cette personne est la gagnante.

Maintenant, la vraie question est, quelle était la probabilité que j'aurais gagné?


Vous recevrez deux entrées:

  • n. C'est le nombre de personnes engagées dans le challenge
  • k. Il s'agit du nombre de personnes (parmi celles-ci n) qui ont 2 vies. Ce numéro vous inclut toujours.

Donc, si j'avais une fonction pet que j'appelais p(10, 5), ce serait la probabilité de gagner le prix où il y a 10 personnes au total, dont 5 n'ont qu'une vie, tandis que 5 (vous y compris) ont 2 vies.


Vous devez afficher la probabilité de gagner soit exactement, soit sous forme décimale. En tout cas, les réponses doivent être à juste et y compris la 4 ème décimale après la virgule décimale. Que vous arrondissiez ou non à ce chiffre dépend de vous.

Votre solution peut être une solution aléatoire qui génère la réponse à la 4 e décimale avec une probabilité élevée . Vous pouvez supposer que le RNG intégré que vous utilisez est vraiment aléatoire et qu'il doit produire la bonne réponse avec une probabilité d'au moins 90%.

De plus, votre code n'a besoin que de fonctionner n, k <= 1000, même si j'ai fourni des cas de test plus grands que ceux pour les curieux.


Cas de test

Remarque: certaines d'entre elles sont des formules générales.

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

Pour quelques autres vérifications, procédez p(n, 1) * ncomme suit:

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
Justin
la source
Je ne connais plus les balises de ce site; si vous pensez à une balise plus appropriée, veuillez la modifier!
Justin
Question étroitement liée à math.se: math.stackexchange.com/q/1669715/72616
Justin
Donc, P (n, k) = ((k-1) / n) P (n, k-1) + ((nk) / n) P (n-1, k) + (1 / n) Q ( n, k-1), où Q (n, k) = ((nk-1) / n) Q (n-1, k) + (k / n) Q (n, k-1) et Q (1 , 0) = 1 ...
Leaky Nun
@KennyLau Je ne vais pas tenter de l'interpréter, mais méfiez-vous du lien math.se, car il utilise une définition légèrement différente de la fonction (je pense qu'elle kest désactivée par une)
Justin
2
Est-il correct de faire une simulation aléatoire avec suffisamment d'essais pour que la réponse soit correcte à la quatrième décimale avec une probabilité élevée, bien que ce ne soit bien sûr pas une certitude?
xnor

Réponses:

2

MATL , 42 octets

:<~QXJx`J`tf1Zry0*1b(-tzq]f1=vts3e8<]6L)Ym

Cela utilise une approche probabiliste (Monte Carlo). L'expérience est exécutée un grand nombre de fois, à partir de laquelle la probabilité est estimée. Le nombre de réalisations est sélectionné pour garantir que le résultat est correct jusqu'à la quatrième décimale avec une probabilité d'au moins 90%. Cependant, cela prend beaucoup de temps et beaucoup de mémoire. Dans le lien ci-dessous, le nombre de réalisations a été réduit d'un facteur 10 6 afin que le programme se termine dans un délai raisonnable; et seule la première décimale est garantie pour être précise avec une probabilité d'au moins 90%.

EDIT (29 juillet 2016): en raison de changements de langue, 6Ldoit être remplacé par 3L. Le lien ci-dessous intègre cette modification.

Essayez-le en ligne!

Contexte

Soit p la probabilité à calculer. L'expérience décrite dans le défi sera lancé pour un nombre n de fois. À chaque fois, soit vous gagnez le prix (« succès »), soit vous ne le gagnez pas. Soit N le nombre de succès. La probabilité souhaitée peut être estimée à partir de N et n . Plus n est grand, plus l'estimation sera précise. La question clé est de savoir comment sélectionner n pour remplir avec la précision souhaitée, à savoir, pour garantir qu'au moins 90% des fois l'erreur sera inférieure à 10 -4 .

Les méthodes de Monte Carlo peuvent être

  • Taille fixe : une valeur de n est fixée à l'avance (puis N est aléatoire);
  • Taille variable : n est déterminé à la volée par les résultats de la simulation.

Dans la deuxième catégorie, une méthode couramment utilisée consiste à fixer N (nombre souhaité de succès) et à continuer de simuler jusqu'à ce que ce nombre de succès soit atteint . Ainsi, n est aléatoire. Cette technique, appelée échantillonnage binomial inverse ou Monte Carlo binomial négatif , présente l'avantage de pouvoir limiter la précision de l'estimateur. Pour cette raison, il sera utilisé ici.

Plus précisément, avec Monte Carlo binomial négatif x = ( N -1) / ( n -1) est un estimateur sans biais de p ; et la probabilité que x s'écarte de p de plus d'un rapport donné peut être supérieure. Selon l'équation (1) de cet article (notez également que les conditions (2) sont remplies), prendre N = 2,75 · 10 8 ou plus garantit que p / x appartient à l'intervalle [1.0001, 0.9999] avec au moins 90% probabilité. En particulier, cela implique que x est correct jusqu'à la 4ème décimale avec au moins 90% de probabilité, comme souhaité.

Explication du code

Le code utilise N = 3e8pour enregistrer un octet. Notez que faire de nombreuses simulations prendrait beaucoup de temps. Le code dans le lien utilise N = 300, qui s'exécute dans un laps de temps plus raisonnable (moins de 1 minute dans le compilateur en ligne pour les premiers cas de test); mais cela garantit seulement que la première décimale est correcte avec une probabilité d'au moins 90%.

:        % Take k implicitly. Range [1 ... k]
<~       % Take n implicitly. Determine if each element in the previous array is
         % less than or equal than n
Q        % Add 1. This gives an array [2 ... 2 1 ... 1]
XJx      % Copy to clipboard J. Delete from stack
`        % Do...while. Each iteration is a Monte Carlo realization, until the 
         % desired nunber of successes is reached
  J      %   Push previously computed array [2 ... 2 1 ... 1]
  `      %   Do...while. Each iteration picks one door and decrements it, until
         %   there is only one
    t    %     Duplicate
    f    %     Indices of non-zero elements of array
    1Zr  %     Choose one of them randomly with uniform distribution
    y0*  %     Copy of array with all values set to 0
    1b(  %     Assign 1 to chosen index
    -    %     Subtract
    tzq  %     Duplicate. Number of nonzero elements minus 1. This is falsy if
         %     there was only one nonzero value; in this case the loop is exited
  ]      %   End do...while
  f1=    %   Index of chosen door. True if it was 1 (success), 0 otherwise
  v      %   Concatenate vertically to results from previous realizations
  ts3e8< %   Duplicate. Is the sum less than 3e8? If so, the loop is exited
]        % End do...while
6L)      % Remove last value (which is always 1)
Ym       % Compute mean. This gives (N-1)/(n-1). Implicitly display
Luis Mendo
la source
Haha, je ne savais pas que 90% rendraient ça difficile :-)
Justin
Oui, la quatrième décimale avec une confiance de 90% est une exigence vraiment forte :-)
Luis Mendo
2

Pyth, 34 octets

Mc|!*HJ-GHch*J+*tHgGtH*gtGHKh-GHKG

Suite de tests

Définit une fonction récursive mémorisée déterministe gprenant n , k comme arguments. g 1000 500renvoie 0.0018008560286627952dans environ 18 secondes (non inclus dans la suite de tests ci-dessus car il expire l'interpréteur en ligne).

Une traduction approximative de Python 3 serait

@memoized
def g(n,k):
    return (not k*(n-k) or (1+(n-k)*((k-1)*g(n,k-1)+g(n-1,k)*(n-k+1)))/(n-k+1))/n
Anders Kaseorg
la source
1

JavaScript (ES6), 65 octets

f=(n,k,d=n-k)=>(!d||(f(n-1,k)*++d*--d+1+(--k&&f(n,k)*k*d))/++d)/n

Mais ne l'essayez pas avec les gros chiffres; même f (30, 10) prend un temps considérable.

Neil
la source