Kontext:
Ein zurückgezogener Milliardär hat eine Spielshow ins Leben gerufen, um die besten und intelligentesten Programmierer der Welt anzulocken. Montags um Mitternacht wählt er aus einem Pool von Bewerbern eine Person als Bewerber der Woche aus und stellt ihnen ein Spiel zur Verfügung. Sie sind der glückliche Kandidat dieser Woche!
Das Spiel dieser Woche:
Der Host bietet Ihnen API-Zugriff auf einen Stapel von 10.000 digitalen Umschlägen. Diese Umschläge sind nach dem Zufallsprinzip sortiert und enthalten einen Dollarwert zwischen 1 und 10.000 US-Dollar (keine zwei Umschläge enthalten denselben Dollarwert).
Sie haben 3 Befehle zur Verfügung:
Read (): Lesen Sie die Dollarzahl im Umschlag oben auf dem Stapel.
Take (): Fügen Sie die Dollar-Zahl in den Umschlag Ihrer Game-Show-Brieftasche hinzu und legen Sie den Umschlag vom Stapel.
Pass (): Nehmen Sie den Umschlag oben auf dem Stapel ab.
Die Regeln:
Wenn Sie Pass () für einen Umschlag verwenden, ist das darin enthaltene Geld für immer verloren.
Wenn Sie Take () für einen Umschlag verwenden, der $ X enthält, dürfen Sie Take () von diesem Punkt an niemals für einen Umschlag verwenden, der <$ X enthält. Nehmen Sie () auf einen dieser Umschläge, um Ihrem Portemonnaie $ 0 hinzuzufügen.
Schreiben Sie einen Algorithmus, der das Spiel mit dem maximalen Geldbetrag beendet.
Wenn Sie eine Lösung in Python schreiben, können Sie diesen Controller zum Testen von Algorithmen verwenden, mit freundlicher Genehmigung von @Maltysen: https://gist.github.com/Maltysen/5a4a33691cd603e9aeca
Wenn Sie den Controller verwenden, können Sie nicht auf globale Variablen zugreifen. Sie können nur die drei bereitgestellten API-Befehle und Variablen mit lokalem Gültigkeitsbereich verwenden. (@Beta Decay)
Hinweise: "Maximal" bedeutet in diesem Fall den Medianwert in Ihrem Portemonnaie, nachdem N> 50 ausgeführt wurden. Ich gehe davon aus, dass der Medianwert für einen gegebenen Algorithmus konvergiert, wenn N auf unendlich ansteigt, obwohl ich mich gerne als falsch erweisen würde. Versuchen Sie stattdessen, den Mittelwert zu maximieren, aber ich habe das Gefühl, dass der Mittelwert mit größerer Wahrscheinlichkeit von einem kleinen N abgelöst wird als der Median.
Bearbeiten: Die Anzahl der Umschläge wurde zur einfacheren Verarbeitung in 10 KB geändert und Take () wurde expliziter.
Bearbeiten 2: Die Preisbedingung wurde im Lichte dieses Beitrags auf Meta entfernt.
Aktuelle Höchstpunktzahlen:
PhiNotPi - 805.479 USD
Reto Koradi - $ 803.960
Dennis - $ 770,272 (überarbeitet)
Alex L. - $ 714.962 (überarbeitet)
quelle
Antworten:
CJam,
$ 87.143$ 700.424$ 720.327$ 727.580$ 770.272Dieses Programm simuliert das gesamte Spiel mehrmals und berechnet den Median.
Wie läuft man?
Ich habe meine Einsendung mit 100.001 Testläufen bewertet:
Ansatz
Für jeden Umschlag gehen wir wie folgt vor:
Schätzen Sie, wie viel Geld durch die Entnahme des Umschlags unweigerlich verloren geht.
Wenn R der Inhalt ist und M das Maximum ist, das genommen wurde, kann der Betrag als R (R-1) / 2 - M (M + 1) / 2 geschätzt werden , was dem Geld alle Umschläge mit dem Inhalt X in gibt Intervall (M, R) enthalten.
Wenn noch keine Umschläge übergeben worden wären, wäre die Schätzung perfekt.
Berechnen Sie den Geldbetrag, der beim Übergeben des Umschlags unweigerlich verloren gehen wird.
Dies ist einfach das Geld, das der Umschlag enthält.
Überprüfen Sie, ob der Quotient von beiden kleiner als 110 + 0,016 E ist , wobei E die Anzahl der verbleibenden Umschläge ist (ohne Umschläge, die nicht mehr genommen werden können).
Wenn ja, nimm. Ansonsten bestanden.
quelle
Python,
$ 680.646$ 714.962Nimmt immer größere Mengen in Schritten von 125 bis 190 US-Dollar auf. Lief mit N = 10.000 und bekam einen Median von $ 714962. Diese Schrittweiten stammen aus Versuchsreihen und sind sicherlich nicht optimal.
Der vollständige Code, einschließlich einer modifizierten Version des @ Maltysen-Controllers, der ein Balkendiagramm druckt, während es ausgeführt wird:
BitCoin-Adresse: 1CBzYPCFFBW1FX9sBTmNYUJyMxMcmL4BZ7
Wow OP geliefert! Vielen Dank @LivingInformation!
quelle
max_taken
in Ihrem eigenen Code beibehalten müssen, da er nicht Teil der offiziellen Spiel-API ist. Aber das ist trivial.read()
,take()
undpass()
Verfahren , die in dem von ihm entsandten Code, da das sind die „3 - Befehle zur Verfügung“ , basierend auf der Definition in der Frage.C ++, 803.960 USD
Das gemeldete Ergebnis ist der Median von 10.001 Spielen.
quelle
C ++, ~ 815.000 US-Dollar
Basiert auf der Lösung von Reto Koradi, wechselt jedoch zu einem ausgefeilteren Algorithmus, sobald 100 (gültige) Hüllkurven übrig sind. Dabei werden zufällige Permutationen gemischt und die am stärksten zunehmende Folge davon berechnet. Es vergleicht die Ergebnisse der Entnahme und Nichtentnahme des Umschlags und wählt gierig die beste Wahl aus.
quelle
Java, 806.899 USD
Dies ist aus einem Versuch von 2501 Runden. Ich arbeite noch daran, es zu optimieren. Ich schrieb zwei Klassen, einen Umschlag und einen Spieler. Der Wrapper instanziiert den Player mit der Anzahl der Umschläge (immer 10000 für das Original) und ruft dann die Methode
takeQ
mit dem Wert des obersten Umschlags auf. Der Spieler kehrt dann zurück,true
wenn er es nimmt,false
wenn er es besteht.Spieler
Verpackung
Eine ausführlichere Erklärung folgt in Kürze, nachdem ich Optimierungen abgeschlossen habe.
Die Grundidee besteht darin, die Belohnung für das Spielen eines Spiels aus einem bestimmten Satz von Umschlägen abschätzen zu können. Wenn der aktuelle Satz von Umschlägen {2,4,5,7,8,9} und der obere Umschlag die 5 ist, gibt es zwei Möglichkeiten:
Wenn wir die erwartete Belohnung von {7,8,9} berechnen und mit der erwarteten Belohnung von {2,4,7,8,9} vergleichen, können wir feststellen, ob es sich lohnt, die 5 zu nehmen.
Nun stellt sich die Frage, wie hoch der erwartete Wert bei einer Reihe von Umschlägen wie {2,4,7,8,9} ist. Ich fand, dass der erwartete Wert proportional zur Gesamtmenge des Geldes in der Menge zu sein scheint, aber umgekehrt proportional zur Quadratwurzel der Anzahl der Umschläge, in die das Geld aufgeteilt ist. Dies ist darauf zurückzuführen, dass mehrere kleine Spiele "perfekt" gespielt wurden, bei denen alle Umschläge einen nahezu identischen Wert haben.
Das nächste Problem ist die Ermittlung der " effektiven Anzahl von Umschlägen". In allen Fällen ist die Anzahl der Umschläge genau bekannt, indem Sie nachverfolgen, was Sie gesehen und getan haben. So etwas wie {234,235,236} ist definitiv drei Umschläge, {231,232,233,234,235} ist definitiv 5, aber {1,2,234,235,236} sollte wirklich als 3 und nicht als 5 Umschläge zählen, da die Umschläge 1 und 2 fast wertlos sind und Sie niemals einen 234er PASSEN würden Sie könnten später eine 1 oder 2 nehmen. Ich hatte die Idee, Shannon-Entropie zu verwenden, um die effektive Anzahl von Umschlägen zu bestimmen.
Ich habe meine Berechnungen auf Situationen ausgerichtet, in denen die Werte der Hüllkurve gleichmäßig über ein Intervall verteilt sind, was während des Spiels passiert. Wenn ich {2,4,7,8,9} nehme und das als Wahrscheinlichkeitsverteilung betrachte, ist seine Entropie 1.50242. Dann
exp()
bekomme ich 4.49254 als effektive Anzahl der Umschläge.Die geschätzte Belohnung von {2,4,7,8,9} ist
30 * 4.4925^-0.5 * 4/3 = 18.87
Die genaue Anzahl ist
18.1167
.Dies ist keine exakte Schätzung, aber ich bin wirklich stolz darauf, wie gut dies zu den Daten passt, wenn die Umschläge gleichmäßig über ein Intervall verteilt sind. Ich bin mir nicht sicher, welcher Multiplikator richtig ist (ich verwende momentan 4/3), aber hier ist eine Datentabelle ohne den Multiplikator.
Die lineare Regression zwischen erwartet und tatsächlich ergibt einen R ^ 2-Wert von 0,999994 .
Mein nächster Schritt, um diese Antwort zu verbessern, besteht darin, die Schätzung zu verbessern, wenn die Anzahl der Umschläge langsam abnimmt. Dies ist der Fall, wenn die Umschläge nicht mehr annähernd gleichmäßig verteilt sind und das Problem allmählich granular wird.
Bearbeiten: Wenn dies Bitcoins wert ist, habe ich gerade eine Adresse an(Dies war hier, als der Herausforderungsautor Preise verteilte.)1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. Vielen Dank!quelle