자바, $ 806,899
이것은 2501 라운드의 시험입니다. 나는 아직도 그것을 최적화하기 위해 노력하고 있습니다. 나는 래퍼와 플레이어라는 두 가지 수업을 썼습니다. 래퍼는 봉투 수 (실제로는 항상 10000)로 플레이어를 인스턴스화 한 다음 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이면 두 가지 가능성이 있습니다.
- {7,8,9}와 함께 5를 가지고 게임을하세요
- 5를 통과하고 {2,4,7,8,9}의 게임을하십시오
{7,8,9}의 예상 보상을 계산하고이를 {2,4,7,8,9}의 예상 보상과 비교하면 5를 복용하는 것이 가치가 있는지 알 수 있습니다.
이제 질문은 {2,4,7,8,9}와 같은 봉투 세트가 주어지면 예상되는 값은 무엇입니까? 예상 값이 세트의 총 금액에 비례하는 것으로 보이지만 돈이 나뉘는 봉투 수의 제곱근에 반비례하는 것으로 나타났습니다. 이것은 모든 봉투의 가치가 거의 같은 여러 개의 작은 게임을 "완벽하게"수행 한 결과입니다.
다음 문제는 " 유효 봉투 수 "를 확인하는 방법 입니다. 모든 경우에 봉투의 수는보고 수행 한 작업을 추적하여 정확하게 알려져 있습니다. {234,235,236}과 같은 것은 확실히 3 개의 봉투이고, {231,232,233,234,235}는 확실히 5이지만, 1과 2는 거의 쓸모가 없으며 234 번을 통과하지 않으므로 {1,2,234,235,236}는 실제로는 5가 아닌 3으로 계산해야합니다. 나중에 1 또는 2를 선택할 수 있습니다. 나는 유효 봉투 수를 결정하기 위해 Shannon 엔트로피를 사용하는 아이디어를 가졌습니다.
엔벨로프의 값이 일정한 간격으로 균일하게 분포되는 상황, 즉 게임 중에 발생하는 상황을 계산 대상으로 삼았습니다. {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 입니다.
이 답변을 개선하기위한 다음 단계는 봉투 수가 적어지기 시작할 때, 즉 봉투가 대략 균일하게 분포되지 않고 문제가 세분화 될 때의 추정을 개선하는 것입니다.
편집 : 이것이 비트 코인의 가치가 있다고 생각되면 방금 주소를 얻었습니다 1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. 감사! (이것은 챌린지 작성자가 상품을 전달할 때부터 시작되었습니다.)