Le contexte:
Un milliardaire reclus a créé un jeu télévisé pour attirer les meilleurs programmeurs du monde. Le lundi à minuit, il choisit une personne parmi un groupe de candidats pour être le candidat de la semaine et leur propose un jeu. Vous êtes l'heureux candidat de cette semaine!
Jeu de cette semaine:
L'hôte vous offre un accès API à une pile de 10 000 enveloppes numériques. Ces enveloppes sont triées au hasard et contiennent en leur sein une valeur en dollars, entre 1 $ et 10 000 $ (il n’existe pas deux enveloppes ayant la même valeur en dollars).
Vous avez 3 commandes à votre disposition:
Lire (): lire le chiffre en dollars dans l'enveloppe en haut de la pile.
Take (): Ajoutez le chiffre en dollars dans l'enveloppe à votre portefeuille de jeu télévisé et sortez l'enveloppe de la pile.
Pass (): Retirez l'enveloppe sur le dessus de la pile.
Les règles:
Si vous utilisez Pass () sur une enveloppe, l'argent à l'intérieur est perdu pour toujours.
Si vous utilisez Take () sur une enveloppe contenant $ X, à partir de ce moment, vous ne pourrez jamais utiliser Take () sur une enveloppe contenant <$ X. Prenez () sur l'une de ces enveloppes ajoutera 0 $ à votre portefeuille.
Écrivez un algorithme qui termine le jeu avec le montant maximal d'argent.
Si vous écrivez une solution en Python, n'hésitez pas à utiliser ce contrôleur pour tester des algorithmes, gracieuseté de @Maltysen: https://gist.github.com/Maltysen/5a4a33691cd603e9aeca
Si vous utilisez le contrôleur, vous ne pouvez pas accéder aux globaux, vous ne pouvez utiliser que les 3 commandes API fournies et les variables de portée locales. (@Beta Decay)
Remarques: "Maximal" dans ce cas signifie la valeur médiane de votre portefeuille après N> 50 exécutions. Je m'attends, bien que j'aimerais qu'on me prouve à tort, que la valeur médiane d'un algorithme donné convergera lorsque N augmentera à l'infini. N'hésitez pas à essayer de maximiser la moyenne à la place, mais j'ai le sentiment que la moyenne est plus susceptible d'être rejetée par un petit N que la médiane.
Modifier: a changé le nombre d'enveloppes à 10k pour un traitement plus facile et a rendu Take () plus explicite.
Edit 2: La condition de prix a été supprimée, à la lumière de ce post sur meta.
Meilleurs scores actuels:
PhiNotPi - 805 479 $
Reto Koradi - 803 960 $
Dennis - 770 272 $ (révisé)
Alex L. - 714 962 $ (révisé)
la source
Réponses:
CJam,
87.143$ 700.424$ 720.327$ 727.580$ 770.272 $Ce programme simule le jeu entier plusieurs fois et calcule la médiane.
Comment courir
J'ai marqué ma soumission en effectuant 100 001 tests:
Approche
Pour chaque enveloppe, nous procédons comme suit:
Estimez le montant d'argent qui sera inévitablement perdu en prenant l'enveloppe.
Si R est le contenu et M est le maximum qui a été pris, le montant peut être estimé comme R (R-1) / 2 - M (M + 1) / 2 , ce qui donne à l'argent toutes les enveloppes avec le contenu X dans le l'intervalle (M, R) contient.
Si aucune enveloppe n'avait encore été passée, l'estimation serait parfaite.
Calculez le montant d'argent qui sera inévitablement perdu en passant l'enveloppe.
C'est simplement l'argent que contient l'enveloppe.
Vérifiez si le quotient des deux est inférieur à 110 + 0,016E , où E est le nombre d'enveloppes restantes (sans compter les enveloppes qui ne peuvent plus être prises).
Si oui, prenez. Sinon, passez.
la source
Python,
680 646$ 714962$Prend des quantités de plus en plus grandes par étapes de taille entre 125 $ et 190 $. A couru avec N = 10 000 et a obtenu une médiane de 714962 $. Ces tailles de pas proviennent d'essais et d'erreurs et ne sont certainement pas optimales.
Le code complet, y compris une version modifiée du contrôleur de @ Maltysen qui imprime un graphique à barres pendant son exécution:
Adresse BitCoin: 1CBzYPCFFBW1FX9sBTmNYUJyMxMcmL4BZ7
Wow OP livré! Merci @LivingInformation!
la source
max_taken
dans votre propre code, car il ne fait pas partie de l'API de jeu officielle. Mais c'est trivial à faire.read()
,take()
et lespass()
méthodes dans le code affiché, puisque ce sont les « 3 commandes à votre disposition » en fonction de la définition de la question.C ++, 803 960 $
Le résultat signalé est la médiane de 10 001 matchs.
la source
C ++, ~ 815 000 $
Basé sur la solution de Reto Koradi, mais passe à un algorithme plus sophistiqué une fois qu'il reste 100 enveloppes (valides), mélangeant les permutations aléatoires et calculant la sous-séquence croissante la plus lourde d'entre elles. Il comparera les résultats de la prise et de la non prise de l'enveloppe, et sélectionnera avidement le meilleur choix.
la source
Java, 806 899 $
Il s'agit d'un essai de 2501 tours. Je travaille toujours sur son optimisation. J'ai écrit deux classes, un wrapper et un joueur. L'encapsuleur instancie le lecteur avec le nombre d'enveloppes (toujours 10000 pour la vraie chose), puis appelle la méthode
takeQ
avec la valeur de l'enveloppe supérieure. Le joueur revient ensuitetrue
s'il le prend,false
s'il le passe.Joueur
Wrapper
Une explication plus détaillée arrivera bientôt, une fois les optimisations terminées.
L'idée centrale est de pouvoir estimer la récompense d'un jeu à partir d'un ensemble d'enveloppes donné. Si le jeu d'enveloppes actuel est {2,4,5,7,8,9} et que l'enveloppe supérieure est le 5, il y a deux possibilités:
Si nous calculons la récompense attendue de {7,8,9} et la comparons à la récompense attendue de {2,4,7,8,9}, nous serons en mesure de dire si prendre le 5 en vaut la peine.
Maintenant, la question est, étant donné un ensemble d'enveloppes comme {2,4,7,8,9} quelle est la valeur attendue? J'ai trouvé que la valeur attendue semble être proportionnelle au montant total de l'argent dans l'ensemble, mais inversement proportionnelle à la racine carrée du nombre d'enveloppes dans lesquelles l'argent est divisé. Cela venait de "parfaitement" jouer à plusieurs petits jeux dans lesquels toutes les enveloppes ont une valeur presque identique.
Le problème suivant est de savoir comment déterminer le " nombre effectif d'enveloppes». Dans tous les cas, le nombre d'enveloppes est connu exactement en gardant une trace de ce que vous avez vu et fait. Quelque chose comme {234,235,236} est certainement trois enveloppes, {231,232,233,234,235} est certainement 5, mais {1,2,234,235,236} devrait vraiment compter comme 3 et non 5 enveloppes car les 1 et 2 sont presque sans valeur, et vous ne PASSERIEZ JAMAIS sur un 234 donc vous pourriez plus tard prendre un 1 ou 2. J'ai eu l'idée d'utiliser l'entropie de Shannon pour déterminer le nombre effectif d'enveloppes.
J'ai ciblé mes calculs sur des situations où les valeurs de l'enveloppe sont uniformément réparties sur un certain intervalle, ce qui se produit pendant le jeu. Si je prends {2,4,7,8,9} et que je la traite comme une distribution de probabilité, son entropie est de 1,50242. Alors je fais
exp()
pour obtenir 4,49254 comme nombre effectif d'enveloppes.La récompense estimée de {2,4,7,8,9} est
30 * 4.4925^-0.5 * 4/3 = 18.87
Le nombre exact est
18.1167
.Ce n'est pas une estimation exacte, mais je suis vraiment très fier de la façon dont cela correspond aux données lorsque les enveloppes sont réparties uniformément sur un intervalle. Je ne suis pas sûr du bon multiplicateur (j'utilise 4/3 pour l'instant) mais voici un tableau de données excluant le multiplicateur.
La régression linéaire entre les valeurs attendues et réelles donne une valeur R ^ 2 de 0,999994 .
Ma prochaine étape pour améliorer cette réponse consiste à améliorer l'estimation lorsque le nombre d'enveloppes commence à devenir petit, c'est-à-dire lorsque les enveloppes ne sont pas réparties de manière approximativement uniforme et lorsque le problème commence à devenir granuleux.
Edit: Si cela est jugé digne des bitcoins, je viens de recevoir une adresse à(C'était ici quand l'auteur du défi distribuait des prix.)1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. Merci!la source