Contexto:
Um bilionário recluso criou um game show para atrair os melhores e mais brilhantes programadores do mundo. Às segundas-feiras, à meia-noite, ele escolhe uma pessoa de um grupo de candidatos para ser o competidor da semana e oferece a eles um jogo. Você é o sortudo participante desta semana!
O jogo desta semana:
O host fornece acesso à API para uma pilha de 10.000 envelopes digitais. Esses envelopes são classificados aleatoriamente e contêm um valor em dólar entre US $ 1 e US $ 10.000 (dois envelopes não contêm o mesmo valor em dólar).
Você tem 3 comandos à sua disposição:
Read (): Leia a figura do dólar no envelope na parte superior da pilha.
Pegue (): adicione a figura do dólar no envelope à sua carteira de game show e tire o envelope da pilha.
Pass (): Retire o envelope na parte superior da pilha.
As regras:
Se você usar Pass () em um envelope, o dinheiro dentro será perdido para sempre.
Se você usar Take () em um envelope contendo $ X, a partir desse momento, nunca poderá usar Take () em um envelope contendo <$ X. Take () em um desses envelopes adicionará US $ 0 à sua carteira.
Escreva um algoritmo que termine o jogo com a quantidade máxima de dinheiro.
Se você estiver escrevendo uma solução em Python, sinta-se à vontade para usar este controlador para testar algoritmos, cortesia de @Maltysen: https://gist.github.com/Maltysen/5a4a33691cd603e9aeca
Se você usar o controlador, não poderá acessar globais, poderá usar apenas os 3 comandos API fornecidos e as variáveis com escopo local. (@Beta Decay)
Notas: "Máximo", neste caso, significa o valor mediano na sua carteira após N> 50 execuções. Espero, apesar de gostar de provar que estou errado, que o valor mediano de um determinado algoritmo converja à medida que N aumenta para o infinito. Sinta-se à vontade para tentar maximizar a média, mas tenho a sensação de que é mais provável que a média seja descartada por um N pequeno do que a mediana.
Editar: alterou o número de envelopes para 10k para facilitar o processamento e tornou Take () mais explícito.
Edit 2: A condição do prêmio foi removida, à luz desta postagem na meta.
Pontuações máximas atuais:
PhiNotPi - $ 805.479
Reto Koradi - $ 803.960
Dennis - US $ 770.272 (revisado)
Alex L. - US $ 714.962 (revisado)
fonte
Respostas:
CJam,
$ 87.143$ 700.424$ 720.327$ 727.580$ 770.272Este programa simula o jogo inteiro várias vezes e calcula a mediana.
Como executar
Marquei minha inscrição fazendo 100.001 execuções de teste:
Aproximação
Para cada envelope, fazemos o seguinte:
Estime a quantidade de dinheiro que inevitavelmente será perdida ao pegar o envelope.
Se R é o conteúdo e M é o máximo que foi obtido, a quantidade pode ser estimada em R (R-1) / 2 - M (M + 1) / 2 , que fornece ao dinheiro todos os envelopes com o conteúdo X no intervalo (M, R) contém.
Se nenhum envelope tivesse sido passado ainda, a estimativa seria perfeita.
Calcule a quantia que inevitavelmente será perdida passando o envelope.
Este é simplesmente o dinheiro que o envelope contém.
Verifique se o quociente de ambos é menor que 110 + 0,016E , onde E é o número de envelopes restantes (sem contar os envelopes que não podem mais ser utilizados).
Se sim, pegue. Caso contrário, passe.
fonte
Python,
$ 680.646$ 714.962Toma quantidades cada vez maiores em etapas de tamanho entre US $ 125 e US $ 190. Funcionou com N = 10.000 e obteve uma mediana de US $ 714962. Esses tamanhos de etapas vieram de tentativa e erro e certamente não são ideais.
O código completo, incluindo uma versão modificada do controlador do @ Maltysen, que imprime um gráfico de barras enquanto é executado:
Endereço BitCoin: 1CBzYPCFFBW1FX9sBTmNYUJyMxMcmL4BZ7
Uau OP entregue! Obrigado @LivingInformation!
fonte
max_taken
seu próprio código, pois ele não faz parte da API oficial do jogo. Mas isso é trivial de se fazer.read()
,take()
epass()
no código postado, pois esses são os "3 comandos à sua disposição" com base na definição na pergunta.C ++, US $ 803.960
O resultado relatado é a mediana dos 10.001 jogos.
fonte
C ++, ~ $ 815.000
Baseado na solução de Reto Koradi, mas alterna para um algoritmo mais sofisticado quando restarem 100 envelopes (válidos), embaralhando permutações aleatórias e calculando a subsequência crescente mais pesada deles. Ele comparará os resultados de pegar e não levar o envelope e selecionará avidamente a melhor opção.
fonte
Java, $ 806.899
Isto é de um teste de 2501 rodadas. Ainda estou trabalhando para otimizá-lo. Eu escrevi duas aulas, um invólucro e um jogador. O invólucro instancia o player com o número de envelopes (sempre 10000 para a coisa real) e depois chama o método
takeQ
com o valor do envelope superior. O jogador então retornatrue
se eles pegarem,false
se passarem.Jogador
Embrulho
Uma explicação mais detalhada estará disponível em breve, depois que eu terminar as otimizações.
A idéia central é poder estimar a recompensa de jogar um jogo de um determinado conjunto de envelopes. Se o conjunto atual de envelopes for {2,4,5,7,8,9} e o envelope superior for o 5, existem duas possibilidades:
Se calcularmos a recompensa esperada de {7,8,9} e compará-la com a recompensa esperada de {2,4,7,8,9}, seremos capazes de dizer se tirar 5 vale a pena.
Agora, a pergunta é: dado um conjunto de envelopes como {2,4,7,8,9} qual é o valor esperado? Descobri que o valor esperado parece ser proporcional à quantidade total de dinheiro no conjunto, mas inversamente proporcional à raiz quadrada do número de envelopes em que o dinheiro é dividido. Isso veio "perfeitamente" jogando vários jogos pequenos nos quais todos os envelopes têm valor quase idêntico.
O próximo problema é como determinar o " número efetivo de envelopes". Em todos os casos, o número de envelopes é conhecido exatamente acompanhando o que você viu e fez. Algo como {234.235.236} é definitivamente três envelopes, {231.232.233.234.235} é definitivamente 5, mas {1.2.234.235.236} deve realmente contar como 3 e não 5 envelopes, porque o 1 e o 2 são quase inúteis, e você nunca passaria em um 234. você poderia pegar um 1 ou 2. Mais tarde, tive a ideia de usar a entropia de Shannon para determinar o número efetivo de envelopes.
Eu direcionei meus cálculos para situações em que os valores do envelope são distribuídos uniformemente por algum intervalo, que é o que acontece durante o jogo. Se eu pegar {2,4,7,8,9} e tratar isso como uma distribuição de probabilidade, sua entropia é 1,50242. Então eu faço
exp()
para obter 4,49254 como o número efetivo de envelopes.A recompensa estimada de {2,4,7,8,9} é
30 * 4.4925^-0.5 * 4/3 = 18.87
O número exato é
18.1167
.Essa não é uma estimativa exata, mas estou realmente orgulhosa de como isso se encaixa nos dados quando os envelopes são distribuídos uniformemente por um intervalo. Não tenho certeza do multiplicador correto (estou usando 4/3 por enquanto), mas aqui está uma tabela de dados excluindo o multiplicador.
A regressão linear entre o esperado e o real fornece um valor de R ^ 2 de 0,999994 .
Meu próximo passo para melhorar esta resposta é melhorar a estimativa quando o número de envelopes começar a ficar pequeno, ou seja, quando os envelopes não estiverem aproximadamente uniformemente distribuídos e quando o problema começar a ficar granulado.
Edit: Se isso é considerado digno de bitcoins, acabei de receber um endereço em(Foi aqui que o autor do desafio estava distribuindo prêmios.)1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. Obrigado!fonte