Esse é um desafio do código-golfe, no qual você precisa criar um programa que atue como uma solução ou uma solução que se modifique para ilustrar o aprendizado de máquina.
fundo
Existe um programa básico de inteligência artificial chamado 'o jogo dos pangolins' descrito aqui . As idéias básicas são que o programa, quando executado pela primeira vez, pergunta:
OK, por favor, pense em algo
É um pangolim?
Você pode então responder:
sim
Nesse caso, diz:
Boa. Isso foi muuuuito fácil.
Ou, se não, diz:
Oh Bem, você venceu então - No que estava pensando?
Para o qual você pode dizer:
um cachorro
Para o que diria
Por favor, faça uma pergunta sobre um cachorro, para que eu possa dizer a diferença entre um cachorro e um pangolim
você pode responder
Come formigas?
Em seguida, perguntaria:
Qual é a resposta para um cachorro?
Para o qual você diria
não
E diria
obrigado
Da próxima vez que for executado, ele fará a pergunta acima e criará uma árvore binária de tais perguntas.
O desafio
Chega de plano de fundo. Esse desafio é escrever um programa de pangolins auto-modificável. As regras são as seguintes:
A saída do programa (como descrito acima) deve ser para
STDERR
. A resposta final sempre será "Bom. Isso foi muuuuito fácil". ou "obrigado". Depois disso, ele deve gerar a versão atual do programa ou uma nova versão do programa que incorpora a perguntaSTDOUT
. Nenhuma resposta escrita em um idioma que não suporte a escrita paraSTDOUT
e /STDERR
ou leituraSTDIN
será válida.Em outras palavras, no UNIX, você poderia invocar o programa assim:
exemplo:
$ mylanguage myprogram > myprogram.1
[dialog goes here]
$ mylanguage myprogram1 > myprogram.2
[dialog goes here]
- O programa precisa usar exatamente os prompts especificados (porque encurtá-los não mostra nenhuma habilidade). Os prompts são (sem as aspas e onde% s é substituído) da seguinte maneira:
Lista:
"OK, please think of something"
"Is it %s?"
"Good. That was soooo easy."
"Oh. Well you win then -- What were you thinking of?"
"Please give me a question about %s, so I can tell the difference between %s and %s"
"What is the answer for %s?"
"Thanks"
Quando esperando respostas sim / não, seu programa deve aceitar
y
ouyes
em qualquer caso, 'sim', en
ouno
em qualquer caso, para 'não'. O que você faz com entradas não conformes é com você. Por exemplo, você pode optar por receber qualquer resposta que comece comy
ouY
como 'sim' e qualquer outra coisa como não.Você pode assumir que os nomes dos itens fornecidos e as perguntas consistem apenas em letras ASCII, números, espaços, hífens, pontos de interrogação, vírgulas, pontos finais, dois pontos e ponto e vírgula, ou seja, eles correspondem ao regex seguinte
^[-?,.;: a-zA-Z]+$
. Se você pode lidar com mais do que isso (especialmente os caracteres citados no idioma escolhido), pode ser convencido, mas não ganha pontos extras.Seu programa não pode ler ou escrever qualquer arquivo (excluindo
STDIN
,STDOUT
eSTDERR
), ou a partir da rede; especificamente, ele não pode ler nem escrever seu próprio código do disco. Seu estado deve ser salvo no próprio código do programa.Quando o programa é executado e adivinha a resposta corretamente, ele deve funcionar exatamente como um quine, ou seja, deve escrever
STDOUT
exatamente no seu próprio código, inalterado.Quando o programa é executado e adivinha a resposta incorretamente, ele deve codificar a nova pergunta fornecida e responder dentro de seu próprio código e gravá-la
STDOUT
em seu próprio código, para que seja capaz de distinguir entre sua suposição original e o novo objeto fornecido, em além de distinguir entre todos os objetos fornecidos anteriormente.Você deve ser capaz de lidar com várias execuções seqüenciais do software para que ele aprenda sobre muitos objetos. Veja aqui exemplos de várias execuções.
As execuções de teste são fornecidas no link na cabeça (obviamente, cobrindo apenas as caixas de diálogo
STDIN
eSTDERR
).As brechas padrão são excluídas.
Respostas:
Lisp comum,
631576Sessão de exemplo
Nomeie o script
pango1.lisp
e execute da seguinte forma (usando SBCL):Outra rodada, adicionando o urso:
Adicionando uma preguiça (testamos o caso em que a resposta é "não"):
Testando o último arquivo:
Observações
"Thanks"
, aqui está ela.(y or n)
, porque eu estou usando ay-or-n-p
função existente . Posso atualizar a resposta para remover esta saída, se necessário.*QUERY-IO*
fluxo bidirecional dedicado à interação do usuário, que é o que estou usando aqui. Saída padrão e interação com o usuário não mexem, o que segue IMHO o espírito da pergunta.SAVE-LISP-AND-DIE
seria uma abordagem melhor na prática.Saída gerada
Aqui está o último script gerado:
Explicações
Uma árvore de decisão pode ser:
"a pangolin"
, que representa uma folha.(question if-true if-false)
ondequestion
está uma pergunta sim / não fechada , como uma sequência, eif-true
eif-false
são as duas subárvores possíveis associadas à pergunta.A
U
função caminha e retorna uma árvore possivelmente modificada. Cada pergunta é feita por sua vez, começando da raiz até chegar a uma folha, enquanto interage com o usuário.O valor retornado para um nó intermediário
(Q Y N)
é(Q (U Y) N)
(resp.(Q Y (U N))
) Se a resposta à perguntaQ
for sim (resp. Não ).O valor retornado para uma folha é a própria folha, se o programa adivinhou corretamente a resposta, ou uma árvore refinada em que a folha é substituída por uma pergunta e dois resultados possíveis, de acordo com os valores obtidos pelo usuário.
Esta parte foi bastante direta. Para imprimir o código-fonte, usamos variáveis de leitor para criar código auto-referencial.
Ao definirO truque ao usar*PRINT-CIRCLE*
como true, evitamos recursões infinitas durante a impressão bonita.WRITE
with:print-circle T
é que a função também pode retornar o valor para o REPL, dependendo da forma de gravação ser a última forma e, portanto, se o REPL não manipular estruturas circulares, como é definido pelo valor padrão padrão de*PRINT-CIRCLE*
, haverá uma recursão infinita. Precisamos apenas garantir que a estrutura circular não seja retornada ao REPL, é por isso que existe um NIL na última posição do LET. Essa abordagem reduz bastante o problema.fonte
(y or n)
é necessário, mas estou tentado a permitir, pois é uma melhoria.Python 2.7.6,
820728 bytes(Pode funcionar em versões diferentes, mas não tenho certeza)
Bem, não é tão curto quanto a resposta do Common Lisp, mas aqui está um código!
fonte
Python 3, 544 bytes
Experimente Online!
As perguntas / respostas / respostas são armazenadas em uma matriz, onde se a matriz armazena três itens (por exemplo
['Does it eat ants',['a pangolin'],['a dog']]
), ela obtém uma resposta para a pergunta e se repete apenas com o conteúdo do segundo ou terceiro item, dependendo da resposta. Quando chega a uma matriz com apenas um item, ele faz a pergunta e, como possui toda a sua origem como código, é capaz de usar o método de junção dividida para inserir a extensão na matriz e adicionar a nova ramificação. .Originalmente, eu escrevi isso sem perceber o requisito de quine, então reler a pergunta e ter que encontrar uma maneira de executar código e usá-lo como uma string eram difíceis, mas acabei encontrando a ideia do bom formato expansível de quine:
fonte
Python 3 , 497 bytes
Muito semelhante à resposta do Harmless para a representação em árvore. Ele recursivamente faz a próxima pergunta, aprofundando a lista, até que haja apenas uma resposta.
Versão ungolfed (sem citar)
fonte