Java, $ 806,899
นี่คือจากการทดลอง 2501 รอบ ฉันยังคงพยายามปรับให้เหมาะสม ฉันเขียนสองคลาสคือเสื้อคลุมและเครื่องเล่น เสื้อคลุมจะยกตัวอย่างผู้เล่นด้วยจำนวนซองจดหมาย (สำหรับของจริงเสมอ 10,000) จากนั้นเรียกวิธีการนั้นtakeQ
ด้วยค่าของซองจดหมายด้านบน ผู้เล่นจะกลับมาtrue
ถ้าพวกเขารับมันfalse
ถ้าพวกเขาผ่านมันไป
ผู้เล่น
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);
}
}
เสื้อคลุม
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;
}
}
}
คำอธิบายโดยละเอียดเพิ่มเติมกำลังจะมาหลังจากฉันเสร็จสิ้นการปรับให้เหมาะสม
แนวคิดหลักคือสามารถประเมินรางวัลจากการเล่นเกมจากซองจดหมายที่กำหนด หากชุดซองจดหมายปัจจุบันคือ {2,4,5,7,8,9} และซองจดหมายด้านบนคือ 5 แสดงว่ามีความเป็นไปได้สองอย่าง:
- ใช้ 5 และเล่นเกมกับ {7,8,9}
- ผ่าน 5 และเล่นเกม {2,4,7,8,9}
หากเราคำนวณรางวัลที่คาดหวังจาก {7,8,9} และเปรียบเทียบกับผลตอบแทนที่คาดหวังจาก {2,4,7,8,9} เราจะสามารถบอกได้ว่าการใช้ 5 มีค่าหรือไม่
ตอนนี้คำถามคือให้ชุดซองจดหมายเช่น {2,4,7,8,9} ค่าที่คาดหวังคืออะไร ฉันพบว่ามูลค่าที่คาดหวังน่าจะเป็นสัดส่วนกับจำนวนเงินทั้งหมดในชุด แต่สัดส่วนแปรผกผันกับสแควร์รูทของจำนวนซองจดหมายที่แบ่งเงินเป็น สิ่งนี้มาจาก "สมบูรณ์แบบ" ในการเล่นเกมเล็ก ๆ หลายเกมซึ่งซองจดหมายทั้งหมดมีค่าเกือบเท่ากัน
ปัญหาต่อไปคือวิธีการระบุ " จำนวนซองจดหมายที่มีประสิทธิภาพ " ในทุกกรณีจำนวนของซองจดหมายเป็นที่รู้จักอย่างแน่นอนโดยการติดตามสิ่งที่คุณเห็นและทำ บางอย่างเช่น {234,235,236} เป็นสามซองแน่นอน {231,232,233,234,235} มี 5 แน่นอน แต่ {1,2,234,235,236} ควรนับเป็น 3 และไม่ใช่ซองจดหมายเพราะ 1 และ 2 เกือบไร้ค่า คุณสามารถรับ 1 หรือ 2 ได้ในภายหลังฉันมีความคิดที่จะใช้นอนส์เอนโทรปีเพื่อกำหนดจำนวนซองจดหมายที่มีประสิทธิภาพ
ฉันตั้งเป้าหมายการคำนวณของฉันกับสถานการณ์ที่ค่าซองจดหมายมีการกระจายอย่างสม่ำเสมอในบางช่วงเวลาซึ่งเป็นสิ่งที่เกิดขึ้นระหว่างเกม ถ้าฉันใช้ {2,4,7,8,9} และถือว่ามันเป็นการกระจายความน่าจะเป็นเอนโทรปีของมันคือ 1.50242 จากนั้นฉันก็exp()
จะได้ 4.49254 เป็นจำนวนซองจดหมายที่มีประสิทธิภาพ
รางวัลโดยประมาณจาก {2,4,7,8,9} คือ 30 * 4.4925^-0.5 * 4/3 = 18.87
18.1167
จำนวนที่แน่นอนคือ
นี่ไม่ใช่การประมาณการที่แน่นอน แต่จริง ๆ แล้วฉันภูมิใจในความเหมาะสมของข้อมูลเมื่อซองจดหมายมีการกระจายอย่างสม่ำเสมอตลอดช่วงเวลา ฉันไม่แน่ใจว่าตัวคูณที่ถูกต้อง (ตอนนี้ฉันใช้ 4/3) แต่นี่คือตารางข้อมูลที่ไม่รวมตัวคูณ
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
การถดถอยเชิงเส้นตรงระหว่างและคาดว่าจะเกิดขึ้นจริงให้R ^ 2 ค่าของ 0.999994
ขั้นตอนต่อไปของฉันในการปรับปรุงคำตอบนี้คือการปรับปรุงการประมาณค่าเมื่อจำนวนซองจดหมายเริ่มลดลงซึ่งก็คือเมื่อซองจดหมายไม่กระจายอย่างสม่ำเสมอและเมื่อปัญหาเริ่มได้รับอย่างละเอียด
แก้ไข: ในกรณีนี้ถือว่าคุ้มค่าของการ Bitcoins 1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
ฉันเพียงแค่มีที่อยู่ที่ ขอบคุณ! (นี่คือที่นี่จากเมื่อผู้เขียนท้าทายได้แจกรางวัล)