Knockout-Wahrscheinlichkeiten

9

Knockout ist ein Basketballspiel, bei dem die Spieler abwechselnd schießen. Es wird als eine Folge von Zwei-Spieler-Wettbewerben gespielt, von denen jeder die Möglichkeit hat, einen dieser Spieler auszuschalten.

Angenommen, die Spieler sind A B C Dund ihre Chancen, einen Korb zu schießen und zu bilden 0.1 0.2 0.3 0.4, sind unabhängig vom anderen Spieler im Wettbewerb. Die beiden Spieler an der Spitze der Linie Aund B"kämpfen". Seitdem Aist er der Verteidiger , der in Gefahr ist, eliminiert zu werden, und er Bist der Angreifer und nicht in Gefahr, sofort eliminiert zu werden. Aschießt zuerst. Wenn es Aschafft, Ahat erfolgreich verteidigt und geht an den hinteren Rand der Linie. Die Zeile würde sich ändern zu B C D A. Wenn Aes nicht schafft, dann Bschießt. Wenn es Bschafft, Aist es raus und Bgeht zum Ende der Linie, so dass die Linie wird C D B. Wenn beides nichtAnoch Bschafft es, wiederholt sich der Vorgang mit erneutem ASchießen, bis entweder Aoder Bein Korb entsteht.

Angenommen, die Linie wurde geändert in B C D A(wurde Aerfolgreich verteidigt). Jetzt Bund C"kämpfe" damit B, der Verteidiger und Cder Angreifer zu sein. Dieser Vorgang wird wiederholt, bis nur noch eine Person übrig ist. Diese Person ist der Gewinner.

Ihre Aufgabe ist es, die Wahrscheinlichkeiten jeder gewinnenden Person zu berechnen, wenn die Chance besteht, dass sie einen Korb macht.

Eingabe :

Eine Liste von Zahlen, wie 0.1 0.2oder 0.5 0.5 0.5 0.5, wobei die n- te Zahl die Chance ist, dass der n- te Spieler einen Korb macht. Sie können diese Eingabe in einem beliebigen Format vornehmen, einschließlich als Parameter für eine Funktion.

Ausgabe :

Eine Liste von Zahlen, wobei die n- te Zahl die Chance ist, dass der n- te Spieler das Spiel gewinnt. Ihre Zahlen müssen in mindestens 90% der Fälle auf mindestens zwei Dezimalstellen genau sein. Dies bedeutet, dass Sie einen simulationsbasierten Ansatz verwenden können. Wenn Ihr Code jedoch nicht simulationsbasiert ist (es wird garantiert , dass eine korrekte Antwort auf mindestens 6 Dezimalstellen zurückgegeben wird), nehmen Sie 30% von Ihrer Punktzahl weg.

Beispiel zwischen 0.5 0.5: Rufen Sie die Spieler Aund B. Sei pdie Wahrscheinlichkeit, dass A gewinnt. Ahat eine 2/3Chance, erfolgreich zu verteidigen (da es eine 1/2Chance gibt, die Apunktet, eine 1/4Chance, die Averfehlt und Bpunktet, und eine 1/4Chance, die sowohl verfehlt als auch der Prozess wiederholt). Wenn er Anicht verteidigt, wird er ausgeschaltet und Bgewinnt. Wenn Averteidigt, wird die Linie B A. Da die Situation symmetrisch ist, die Wahrscheinlichkeit Aist zu gewinnen (1 - p). Wir bekommen:

p = 2/3 * (1 - p) + 1/3 * 0. Lösen bekommen wir p = 2/5. Die Ausgabe sollte 2/5 3/5oder sein 0.4 0.6.

Ich bin nicht gut genug mit der Wahrscheinlichkeit, komplexere Beispiele zu machen.

Wenn Sie weitere Testfälle benötigen, sind hier einige:

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
quelle

Antworten:

4

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

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

Online-Demo . Dies ist eine rekursive Funktion, die ein Array von Doubles verwendet und ein Array von Doubles zurückgibt. Die Online-Demo enthält eine kleine Menge Gerüste, um die Funktion auszuführen und die Ausgabe für die Anzeige zu formatieren.

Präparation

Das Grundprinzip ist, dass wenn noch n > 1Spieler übrig sind, einer von ihnen der nächste sein muss, der ausgeschaltet wird. Darüber hinaus hängt die Reihenfolge der Warteschlange danach nur von der ursprünglichen Reihenfolge der Warteschlange und davon ab, wer ausgeschlagen wird. So können wir nrekursive Anrufe tätigen, die Gewinnwahrscheinlichkeiten für jeden Spieler in jedem Fall berechnen und dann nur noch angemessen gewichten und addieren.

Ich werde die Eingabewahrscheinlichkeiten als bezeichnen [p_0 p_1 ... p_{n-1}]. Lassen Sie f(a,b)die Wahrscheinlichkeit bezeichnen , die agegen zu verteidigen versagt b. In einem bestimmten Runde, die Wahrscheinlichkeit , dass aerfolgreich ist verteidigt p_a, die Wahrscheinlichkeit , dass bSchläge aaus sind (1-p_a)*p_b, und die Wahrscheinlichkeit , dass es geht um eine neue Runde ist (1-p_a)*(1-p_b). Wir können entweder eine explizite Summe einer geometrischen Progression machen oder wir können argumentieren, dass die beiden geometrischen Progressionen proportional zueinander sind, um dies zu begründen f(a,b) = (1-p_a)*p_b / (p_a + (1-p_a)*p_b).

Dann können wir ein Level auf volle Runden der Linie erhöhen. Die Wahrscheinlichkeit, dass der erste Spieler ausgeschieden ist, ist f(0,1); die Wahrscheinlichkeit, dass der zweite Spieler ausgeschlagen wird, ist (1-f(0,1)) * f(1,2); der dritte Spieler ist (1-f(0,1)) * (1-f(1,2)) * f(2,3); usw., bis der letzte mit Wahrscheinlichkeit ausgeschlagen ist \prod_i (1-f(i,i+1)) * f(n-1,0). Das gleiche Argument über geometrische Progressionen erlaubt es uns, diese Wahrscheinlichkeiten als Gewichte mit Normalisierung um einen Faktor von zu verwenden 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
quelle