Java, $ 806.899
Đây là từ một thử nghiệm của 2501 vòng. Tôi vẫn đang làm việc để tối ưu hóa nó. Tôi đã viết hai lớp, một trình bao bọc và một người chơi. Trình bao bọc khởi tạo trình phát với số lượng phong bì (luôn là 10000 cho thực tế), sau đó gọi phương thức takeQ
với giá trị của phong bì trên cùng. Người chơi sau đó trả lại true
nếu họ lấy nó, false
nếu họ vượt qua nó.
Người chơi
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);
}
}
Vỏ bánh
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;
}
}
}
Một lời giải thích chi tiết hơn sẽ đến sớm, sau khi tôi hoàn thành việc tối ưu hóa.
Ý tưởng cốt lõi là có thể ước tính phần thưởng từ việc chơi trò chơi từ một bộ phong bì nhất định. Nếu bộ phong bì hiện tại là {2,4,5,7,8,9} và phong bì trên cùng là 5, thì có hai khả năng:
- Lấy số 5 và chơi một trò chơi với {7,8,9}
- Vượt qua 5 và chơi một trò chơi {2,4,7,8,9}
Nếu chúng ta tính toán phần thưởng dự kiến là {7,8,9} và so sánh với phần thưởng dự kiến là {2,4,7,8,9}, chúng ta sẽ có thể biết liệu lấy 5 có xứng đáng hay không.
Bây giờ câu hỏi là, đưa ra một bộ phong bì như {2,4,7,8,9} giá trị mong đợi là gì? Tôi thấy giá trị mong đợi dường như tỷ lệ thuận với tổng số tiền trong tập hợp, nhưng tỷ lệ nghịch với căn bậc hai của số lượng phong bì mà số tiền được chia thành. Điều này xuất phát từ việc "hoàn hảo" chơi một số trò chơi nhỏ trong đó tất cả các phong bì có giá trị gần như giống hệt nhau.
Vấn đề tiếp theo là làm thế nào để xác định " số lượng phong bì hiệu quả ". Trong mọi trường hợp, số lượng phong bì được biết chính xác bằng cách theo dõi những gì bạn đã thấy và thực hiện. Một cái gì đó như {234,235,236} chắc chắn là ba phong bì, {231,232,233,234,235} chắc chắn là 5, nhưng {1,2,234,235,236} thực sự nên được tính là 3 và không phải 5 phong bì vì 1 và 2 gần như không có giá trị sau này bạn có thể lấy 1 hoặc 2. Tôi có ý tưởng sử dụng entropy của Shannon để xác định số lượng phong bì hiệu quả.
Tôi đã nhắm mục tiêu tính toán của mình vào các tình huống trong đó các giá trị của phong bì được phân phối đồng đều trong một khoảng thời gian, đó là những gì xảy ra trong trò chơi. Nếu tôi lấy {2,4,7,8,9} và coi đó là phân phối xác suất, thì entropy của nó là 1.50242. Sau đó, tôi làm exp()
để có được 4,49254 là số phong bì hiệu quả.
Phần thưởng ước tính từ {2,4,7,8,9} là 30 * 4.4925^-0.5 * 4/3 = 18.87
Con số chính xác là 18.1167
.
Đây không phải là một ước tính chính xác, nhưng tôi thực sự tự hào về việc dữ liệu này phù hợp với dữ liệu như thế nào khi các phong bì được phân phối đồng đều trong một khoảng thời gian. Tôi không chắc chắn về số nhân chính xác (hiện tôi đang sử dụng 4/3) nhưng đây là bảng dữ liệu không bao gồm số nhân.
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
Hồi quy tuyến tính giữa dự kiến và thực tế cho giá trị R ^ 2 là 0,999999 .
Bước tiếp theo của tôi để cải thiện câu trả lời này là cải thiện ước lượng khi số lượng phong bì bắt đầu nhỏ đi, đó là khi các phong bì không được phân phối đồng đều và khi vấn đề bắt đầu có dạng hạt.
Chỉnh sửa: Nếu điều này được coi là xứng đáng với bitcoin, tôi chỉ cần có một địa chỉ tại 1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. Cảm ơn! (Đây là ở đây từ khi tác giả thách thức đang trao giải.)