Java, $ 806.899
Questo proviene da una prova di 2501 colpi. Sto ancora lavorando per ottimizzarlo. Ho scritto due classi, un wrapper e un giocatore. Il wrapper crea un'istanza per il giocatore con il numero di buste (sempre 10000 per la cosa reale), quindi chiama il metodo takeQ
con il valore della busta superiore. Il giocatore quindi ritorna true
se lo prende, false
se lo supera.
Giocatore
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);
}
}
involucro
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;
}
}
}
Una spiegazione più dettagliata arriverà presto, dopo che avrò finito le ottimizzazioni.
L'idea principale è quella di essere in grado di stimare la ricompensa giocando a un determinato set di buste. Se l'attuale set di buste è {2,4,5,7,8,9} e la busta superiore è 5, allora ci sono due possibilità:
- Prendi il 5 e gioca con {7,8,9}
- Passa il 5 e gioca una partita di {2,4,7,8,9}
Se calcoliamo la ricompensa attesa di {7,8,9} e la confrontiamo con la ricompensa attesa di {2,4,7,8,9}, saremo in grado di dire se vale la pena prendere il 5.
Ora la domanda è, dato un set di buste come {2,4,7,8,9} qual è il valore atteso? Ho scoperto che il valore atteso sembra essere proporzionale alla quantità totale di denaro nell'insieme, ma inversamente proporzionale alla radice quadrata del numero di buste in cui è diviso il denaro. Questo deriva dal "perfetto" gioco di diversi piccoli giochi in cui tutte le buste hanno un valore quasi identico.
Il prossimo problema è come determinare il " numero effettivo di buste". In tutti i casi, il numero di buste è noto esattamente tenendo traccia di ciò che hai visto e fatto. Qualcosa come {234.235.236} è sicuramente tre buste, {231.232.233.234.235} è sicuramente 5, ma {1.2.234.235.236} dovrebbe davvero contare come 3 e non 5 buste perché l'1 e il 2 sono quasi senza valore e non passeresti mai su un 234 quindi in seguito potresti prendere un 1 o 2. Ho avuto l'idea di usare l'entropia di Shannon per determinare il numero effettivo di buste.
Ho indirizzato i miei calcoli a situazioni in cui i valori della busta sono distribuiti uniformemente su un certo intervallo, che è ciò che accade durante il gioco. Se prendo {2,4,7,8,9} e lo considero una distribuzione di probabilità, la sua entropia è 1,50242. Quindi faccio exp()
4.49254 come numero effettivo di buste.
La ricompensa stimata da {2,4,7,8,9} è 30 * 4.4925^-0.5 * 4/3 = 18.87
Il numero esatto è 18.1167
.
Questa non è una stima esatta, ma in realtà sono davvero orgoglioso di quanto bene si adatta ai dati quando le buste sono distribuite uniformemente su un intervallo. Non sono sicuro del moltiplicatore corretto (sto usando 4/3 per ora) ma ecco una tabella di dati che esclude il moltiplicatore.
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
La regressione lineare tra atteso e reale fornisce un valore R ^ 2 di 0.999994 .
Il mio prossimo passo per migliorare questa risposta è migliorare la stima quando il numero di buste inizia a ridursi, ovvero quando le buste non sono distribuite approssimativamente in modo uniforme e quando il problema inizia a diventare granulare.
Modifica: se questo è considerato degno di bitcoin, ho appena ricevuto un indirizzo su 1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. Grazie! (Questo è stato da quando l'autore della sfida distribuiva i premi.)