Editar: este quebra-cabeça também é conhecido como "Enigma de Einstein"
O Who é dono da Zebra (você pode experimentar a versão online aqui ) é um exemplo de um conjunto clássico de quebra-cabeças e aposto que a maioria das pessoas no Stack Overflow pode resolvê-lo com papel e caneta. Mas como seria uma solução programática?
Com base nas pistas listadas abaixo ...
- Existem cinco casas.
- Cada casa tem sua própria cor única.
- Todos os proprietários de casas são de diferentes nacionalidades.
- Todos eles têm animais de estimação diferentes.
- Todos eles bebem bebidas diferentes.
- Todos eles fumam cigarros diferentes.
- O inglês mora na casa vermelha.
- O sueco tem um cachorro.
- O dinamarquês bebe chá.
- A casa verde fica no lado esquerdo da casa branca.
- Eles tomam café na casa verde.
- O homem que fuma Pall Mall tem pássaros.
- Na casa amarela, eles fumam Dunhill.
- Na casa do meio, eles bebem leite.
- O norueguês vive na primeira casa.
- O homem que fuma Blend mora na casa ao lado da casa com gatos.
- Na casa ao lado da casa onde eles têm um cavalo, eles fumam Dunhill.
- O homem que fuma Blue Master bebe cerveja.
- O alemão fuma Prince.
- O norueguês vive ao lado da casa azul.
- Eles bebem água na casa ao lado da casa onde fumam Blend.
... quem é o dono da Zebra?
language-agnostic
logic
constraint-programming
zebra-puzzle
activout.se
fonte
fonte
Respostas:
Aqui está uma solução em Python baseada em programação de restrições:
Resultado:
Demora 0,6 segundos (CPU 1,5 GHz) para encontrar a solução.
A resposta é "O alemão possui zebra".
Para instalar o
constraint
módulo viapip
: pip install python-constraintPara instalar manualmente:
baixar:
$ wget https://pypi.python.org/packages/source/p/python-constraint/python-constraint-1.2.tar.bz2#md5=d58de49c85992493db53fcb59b9a0a45
extrato (Linux / Mac / BSD):
$ bzip2 -cd python-constraint-1.2.tar.bz2 | tar xvf -
extrato (Windows, com 7zip ):
> 7z e python-restrição-1.2.tar.bz2
> 7z e python-restrição-1.2.tar
instalar:
$ cd python-constraint-1.2
$ instalação do python setup.py
fonte
pip install python-constraint
? Eu fiz exatamente isso há um momento e parece dar a saída esperada.Em Prolog, podemos instanciar o domínio apenas selecionar elementos de que :) (fazendo escolhas mutuamente exclusivas , para a eficiência). Usando SWI-Prolog,
É executado instantaneamente:
fonte
Um pôster já mencionou que o Prolog é uma solução potencial. Isso é verdade e é a solução que eu usaria. Em termos mais gerais, esse é um problema perfeito para um sistema de inferência automatizado. Prolog é uma linguagem de programação lógica (e intérprete associado) que forma esse sistema. Basicamente, permite concluir fatos a partir de declarações feitas usando lógica de primeira ordem . O FOL é basicamente uma forma mais avançada de lógica proposicional. Se você decidir que não deseja usar o Prolog, poderá usar um sistema semelhante de sua própria criação usando uma técnica como modus ponens para executar as conclusões.
É claro que você precisará adicionar algumas regras sobre zebras, uma vez que não são mencionadas em nenhum lugar ... Acredito que a intenção é que você possa descobrir os outros 4 animais de estimação e assim deduzir que o último é a zebra? Você deseja adicionar regras que afirmam que uma zebra é um dos animais de estimação, e cada casa pode ter apenas um animal de estimação. Colocar esse tipo de conhecimento de "senso comum" em um sistema de inferência é o maior obstáculo ao uso da técnica como uma verdadeira IA. Existem alguns projetos de pesquisa, como o Cyc, que tentam fornecer esse conhecimento comum por meio da força bruta. Eles encontraram uma quantidade interessante de sucesso.
fonte
Compatível com SWI-Prolog:
No intérprete:
fonte
Aqui está como eu iria sobre isso. Primeiro eu geraria todas as n-tuplas ordenadas
5 ^ 6 desses, 15625, facilmente gerenciáveis. Depois, filtraria as condições booleanas simples. há dez deles, e cada um deles espera filtrar 8/25 das condições (1/25 das condições contêm um sueco com um cachorro, 16/25 contém um não sueco com um não cachorro) . É claro que eles não são independentes, mas depois de filtrá-los, não deve haver muitos.
Depois disso, você terá um bom problema gráfico. Crie um gráfico com cada nó representando uma das n-tuplas restantes. Adicione arestas ao gráfico se as duas extremidades contiverem duplicatas em alguma posição de n-tupla ou violarem quaisquer restrições 'posicionais' (há cinco delas). A partir daí, você está quase em casa, procure no gráfico um conjunto independente de cinco nós (sem nenhum dos nós conectados pelas bordas). Se não houver muitos, você poderá gerar exaustivamente todas as 5 tuplas de n-tuplas e filtrá-las novamente.
Este poderia ser um bom candidato para o código de golfe. Alguém provavelmente pode resolvê-lo em uma linha com algo como haskell :)
reflexão tardia: A passagem inicial do filtro também pode eliminar informações das restrições posicionais. Não muito (1/25), mas ainda significativo.
fonte
Outra solução Python, desta vez usando o PyKE (Python Knowledge Engine) do Python. É mais detalhado do que usar o módulo "restrição" do Python na solução do @JFSebastian, mas fornece uma comparação interessante para quem procura um mecanismo de conhecimento bruto para esse tipo de problema.
clues.kfb
Relations.krb
driver.py (na verdade maior, mas essa é a essência)
Saída de amostra:
Fonte: https://github.com/DreadPirateShawn/pyke-who-owns-zebra
fonte
Aqui está um trecho da solução completa usando o NSolver , publicado no Einstein's Riddle em C # :
fonte
Aqui está uma solução direta no CLP (FD) (consulte também clpfd):
Executá-lo produz:
fonte
neighbor(X,Y) :- abs(X-Y) #= 1.
No PAIP (capítulo 11), Norvig resolve o quebra-cabeça da zebra usando um Prolog embutido no Lisp .
fonte
Solução ES6 (Javascript)
Com muitos geradores ES6 e um pouco de lixo . Você precisará do Babel para executar isso.
Resultado:
O tempo de execução é de cerca de 2,5 segundos para mim, mas isso pode ser melhorado alterando a ordem das regras. Decidi manter a ordem original para maior clareza.
Obrigado, este foi um desafio legal!
fonte
Este é realmente um problema de solução de restrições. Você pode fazer isso com um tipo generalizado de propagação de restrições em linguagens de programação lógica. Temos uma demonstração específica para o problema da Zebra no sistema ALE (mecanismo de lógica do atributo):
http://www.cs.toronto.edu/~gpenn/ale.html
Aqui está o link para a codificação de um quebra-cabeça simplificado da Zebra:
http://www.cs.toronto.edu/~gpenn/ale/files/grammars/baby.pl
Fazer isso de forma eficiente é outra questão.
fonte
A maneira mais fácil de resolver esses problemas programaticamente é usar loops aninhados em todas as permutações e verificar se o resultado satisfaz os predicados da pergunta. Muitos dos predicados podem ser içados do loop interno para os loops externos, a fim de reduzir drasticamente a complexidade computacional até que a resposta possa ser calculada em um tempo razoável.
Aqui está uma solução F # simples derivada de um artigo no F # Journal :
A saída obtida em 9ms é:
fonte
O exemplo do Microsoft Solver Foundation de: https://msdn.microsoft.com/en-us/library/ff525831%28v=vs.93%29.aspx?f=255&MSPPError=-2147217396
fonte
Esta é uma solução MiniZinc para o quebra-cabeça de zebra, conforme definido na Wikipedia:
Solução:
fonte