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
import java.lang.Math;
public class Player {
public int[] V;
public Player(int s) {
V = new int[s];
for (int i = 0; i < V.length; i++) {
V[i] = i + 1;
}
// System.out.println();
}
public boolean takeQ(int x) {
// System.out.println("look " + x);
// http://www.programmingsimplified.com/java/source-code/java-program-for-binary-search
int first = 0;
int last = V.length - 1;
int middle = (first + last) / 2;
int search = x;
while (first <= last) {
if (V[middle] < search)
first = middle + 1;
else if (V[middle] == search)
break;
else
last = middle - 1;
middle = (first + last) / 2;
}
int i = middle;
if (first > last) {
// System.out.println(" PASS");
return false; // value not found, so the envelope must not be in the list
// of acceptable ones
}
int[] newVp = new int[V.length - 1];
for (int j = 0; j < i; j++) {
newVp[j] = V[j];
}
for (int j = i + 1; j < V.length; j++) {
newVp[j - 1] = V[j];
}
double pass = calcVal(newVp);
int[] newVt = new int[V.length - i - 1];
for (int j = i + 1; j < V.length; j++) {
newVt[j - i - 1] = V[j];
}
double take = V[i] + calcVal(newVt);
// System.out.println(" take " + take);
// System.out.println(" pass " + pass);
if (take > pass) {
V = newVt;
// System.out.println(" TAKE");
return true;
} else {
V = newVp;
// System.out.println(" PASS");
return false;
}
}
public double calcVal(int[] list) {
double total = 0;
for (int i : list) {
total += i;
}
double ent = 0;
for (int i : list) {
if (i > 0) {
ent -= i / total * Math.log(i / total);
}
}
// System.out.println(" total " + total);
// System.out.println(" entro " + Math.exp(ent));
// System.out.println(" count " + list.length);
return total * (Math.pow(Math.exp(ent), -0.5) * 4.0 / 3);
}
}
Verpackung
import java.lang.Math;
import java.util.Random;
import java.util.ArrayList;
import java.util.Collections;
public class Controller {
public static void main(String[] args) {
int size = 10000;
int rounds = 2501;
ArrayList<Integer> results = new ArrayList<Integer>();
int[] envelopes = new int[size];
for (int i = 0; i < envelopes.length; i++) {
envelopes[i] = i + 1;
}
for (int round = 0; round < rounds; round++) {
shuffleArray(envelopes);
Player p = new Player(size);
int cutoff = 0;
int winnings = 0;
for (int i = 0; i < envelopes.length; i++) {
boolean take = p.takeQ(envelopes[i]);
if (take && envelopes[i] >= cutoff) {
winnings += envelopes[i];
cutoff = envelopes[i];
}
}
results.add(winnings);
}
Collections.sort(results);
System.out.println(
rounds + " rounds, median is " + results.get(results.size() / 2));
}
// stol... I mean borrowed from
// http://stackoverflow.com/questions/1519736/random-shuffling-of-an-array
static Random rnd = new Random();
static void shuffleArray(int[] ar) {
for (int i = ar.length - 1; i > 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
}
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:
- Nimm die 5 und spiele ein Spiel mit {7,8,9}
- Übergeben Sie die 5 und spielen Sie eine Partie {2,4,7,8,9}
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.
Set of Envelopes Total * (e^entropy)^-0.5 Actual Score
{1,2,3,4,5,6,7,8,9,10} 18.759 25.473
{2,3,4,5,6,7,8,9,10,11} 21.657 29.279
{3,4,5,6,7,8,9,10,11,12} 24.648 33.125
{4,5,6,7,8,9,10,11,12,13} 27.687 37.002
{5,6,7,8,9,10,11,12,13,14} 30.757 40.945
{6,7,8,9,10,11,12,13,14,15} 33.846 44.900
{7,8,9,10,11,12,13,14,15,16} 36.949 48.871
{8,9,10,11,12,13,14,15,16,17} 40.062 52.857
{9,10,11,12,13,14,15,16,17,18} 43.183 56.848
{10,11,12,13,14,15,16,17,18,19} 46.311 60.857
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 1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. Vielen Dank! (Dies war hier, als der Herausforderungsautor Preise verteilte.)