Recentemente, no recém-lançado Puzzling.SE , havia um problema sobre espiões jogando pedras em um rio que era realmente bastante desafiador:
Dois espiões devem passar entre si dois números secretos (um número por espião), despercebidos pelos inimigos. Eles concordaram em um método para fazer isso usando apenas 26 pedras indistinguíveis com antecedência.
Eles se encontram em um rio, onde há uma pilha de 26 pedras. Começando com o primeiro espião, eles se revezam jogando um grupo de pedras no rio: o primeiro espião lança um número de pedras, depois o segundo, depois o primeiro novamente ...
Cada espião deve jogar pelo menos uma pedra no seu turno, até que todas as pedras acabem.
Eles observam todos os arremessos e divergem quando não há mais pedras. Eles mantêm silêncio o tempo todo e nenhuma informação é trocada, exceto o número de pedras jogadas a cada turno.
Como eles podem trocar os números com sucesso se os números podem ser de 1 a M?
Sua tarefa é criar um par de programas spy1
e spy2
isso pode resolver esse problema da maneira mais alta possível M
.
Seus programas levarão um número 1
para o escolhido M
como entrada. Em seguida, spy1
produzirá um número que representa o número de pedras que ele joga no rio, que será introduzido no spy2
qual também produzirá um número para o qual será inserido spy1
, e assim por diante até que os números produzidos sejam somados 26
. No final do lançamento, cada programa produzirá o número que acredita que o outro programa tinha, que deve corresponder ao número que foi realmente inserido no outro programa.
Seu programa deve funcionar para todos os possíveis pares ordenados de números em (i, j)
que ambos i
e j
podem variar de 1
até M
.
O programa que trabalha para o maior M
será o vencedor, com a primeira resposta a ser publicada quebrando o empate. Além disso, concederei uma recompensa de +100 reputação à primeira solução comprovada para o trabalho M >= 2286
e +300 à primeira solução comprovadamente trabalhada M >= 2535
.
Respostas:
C #, M = 2535
Isso implementa * o sistema que eu descrevi matematicamente no tópico que provocou esse concurso. Eu reivindico o bônus de 300 representantes. O programa autoteste se você o executa sem argumentos de linha de comando ou
--test
como argumento de linha de comando; para o espião 1, corra com--spy1
, e para o espião 2 com--spy2
. Em cada caso, pega o número que devo comunicar a partir de stdin e, em seguida, lança através de stdin e stdout.* Na verdade, encontrei uma otimização que faz uma enorme diferença (de alguns minutos para gerar a árvore de decisão a menos de um segundo); a árvore que gera é fundamentalmente a mesma, mas ainda estou trabalhando em uma prova disso. Se você deseja uma implementação direta do sistema que eu descrevi em outro lugar, consulte a revisão 2 , embora possa querer suportar o log extra
Main
e as melhores comunicações entre threadsTestSpyIO
.Se você deseja um caso de teste concluído em menos de um minuto, altere
N
para16
eM
para87
.Instruções para usuários do Linux
Você precisará
mono-csc
compilar (em sistemas baseados no Debian, está nomono-devel
pacote) emono
executar (mono-runtime
pacote). Então os encantamentos sãoetc.
fonte
yum install mono-core
(como root). 2.dmcs Puzzle625.cs
3.mono Puzzle625.exe --test
Programa Python Tester
Eu acho que seria útil ter um programa de teste que possa verificar se sua implementação está funcionando. Ambos os scripts abaixo funcionam com o Python 2 ou o Python 3.
Programa testador (
tester.py
):Protocolo: Os dois programas espiões especificados na linha de comando serão executados. Espera-se que eles interajam apenas através do stdin / stdout. Cada programa receberá seu número atribuído como a primeira linha de entrada. Em cada turno, o espião 1 gera o número de pedras a serem lançadas, o espião 2 lê um número de stdin (representando o lançamento do espião 1) e, em seguida, eles repetem (com as posições invertidas). Quando um dos espiões determina que 26 pedras foram jogadas, elas param e emitem seu palpite para o número do outro espião.
Exemplo de sessão com um spy1 compatível (
>
indica entrada para o spy)Se você escolher um muito grande M, e leva muito tempo para ser executado, você pode alternar
test(
paratestrand(
na última linha para executar testes aleatórios. Neste último caso, deixe o programa em execução por pelo menos alguns milhares de tentativas para aumentar a confiança.Exemplo de programa (
spy.py
), para M = 42:Exemplo de uso:
fonte
Java, M = 2535
OK, aqui está a minha implementação. A cada passo, um espião faz um movimento. Cada movimento possível representa um intervalo de códigos. O espião escolhe a jogada correspondente ao seu código secreto. À medida que jogam mais pedras, a variedade de códigos possíveis reduz até que, no final, para ambos os espiões, apenas um código seja possível de acordo com os movimentos que eles fizeram.
Para recuperar os códigos secretos, você pode reproduzir todas as jogadas e calcular os intervalos de códigos correspondentes. No final, resta apenas um código para cada espião, que é o código secreto que ele queria transmitir.
Infelizmente, o algoritmo conta com uma grande tabela pré-computada com centenas de milhares de números inteiros. O método não poderia ser aplicado mentalmente com mais de 8 a 10 pedras, talvez.
O primeiro arquivo implementa o algoritmo do Spy. A parte estática precomputa uma
codeCount
tabela que é usada posteriormente para calcular cada movimento. A segunda parte implementa 2 procedimentos, um para selecionar quantas pedras jogar, e o outro para repetir um movimento para ajudar a reconstruir os códigos secretos.O segundo arquivo testa a classe Spy extensivamente. O método
simulate
simula o processo. Ele usa a classe Spy para gerar uma sequência de lançamentos a partir dos códigos secretos e depois reconstrói os códigos a partir da sequência.Spy.java
ThrowingStones.java
Para referência, a matriz codeCount pré-computada contém os seguintes valores:
Isso estava diretamente relacionado aos conjuntos Tk de Peter Taylor. Nós temos:
fonte
range
campos. Mas estou muito intrigado com o seu método de calcular a tabela. Você tem uma prova de correção? E você está interessado em colaborar em um artigo que discute o problema e calcule sua solução?ksh / zsh, M = 126
Neste sistema simples, cada espião lança dígitos binários para o outro espião. Em cada lançamento, a primeira pedra é ignorada, as seguintes são cada bit 0 e a última é o bit 1. Por exemplo, para lançar 20, um espião jogaria 4 pedras (ignore 0, 2, adicione 4), então jogue 3 pedras (ignore, 8, adicione 16), porque 4 + 16 = 20.
O conjunto de números não é contíguo. 0 a 126 estão dentro, mas 127 está fora. (Se ambos os espiões têm 127, precisam de 28 pedras, mas 26). Depois, 128 a 158 entram, 159 sai, 160 a 174 entram, 175 está fora, 175 estão fora, 176 a 182 estão dentro, 183 estão fora, 184 a 186 está dentro, 187 está fora e assim por diante.
Execute uma troca automática com
ksh spy.sh 125 126
, ou execute espiões individuais comksh spy.sh spy1 125
eksh spy.sh spy2 126
. Aqui,ksh
pode ser ksh93, pdksh ou zsh.EDIT 14 Jun 2014: Corrija um problema com alguns co-processos no zsh. Eles ficariam ociosos para sempre e não conseguiriam sair, até que o usuário os matasse.
fonte