Editar: este rompecabezas también se conoce como "Einstein's Riddle"
El Quién posee la cebra (puede probar la versión en línea aquí ) es un ejemplo de un conjunto clásico de rompecabezas y apuesto a que la mayoría de las personas en Stack Overflow pueden resolverlo con lápiz y papel. Pero, ¿cómo sería una solución programática?
Según las pistas que se enumeran a continuación ...
- Hay cinco casas.
- Cada casa tiene su propio color único.
- Todos los dueños de casa son de diferentes nacionalidades.
- Todos tienen diferentes mascotas.
- Todos beben diferentes bebidas.
- Todos fuman cigarrillos diferentes.
- El inglés vive en la casa roja.
- El sueco tiene un perro.
- El danés bebe té.
- La casa verde está en el lado izquierdo de la casa blanca.
- Beben café en la casa verde.
- El hombre que fuma Pall Mall tiene pájaros.
- En la casa amarilla fuman Dunhill.
- En la casa del medio beben leche.
- El noruego vive en la primera casa.
- El hombre que fuma Blend vive en la casa de al lado con gatos.
- En la casa al lado de la casa donde tienen un caballo, fuman Dunhill.
- El hombre que fuma Blue Master bebe cerveza.
- El alemán fuma Príncipe.
- El noruego vive al lado de la casa azul.
- Beben agua en la casa al lado de la casa donde fuman Blend.
... ¿quién es el dueño de la cebra?
language-agnostic
logic
constraint-programming
zebra-puzzle
activout.se
fuente
fuente
Respuestas:
Aquí hay una solución en Python basada en la restricción de programación:
Salida:
Se necesitan 0.6 segundos (CPU 1.5GHz) para encontrar la solución.
La respuesta es "el alemán posee cebra".
Para instalar el
constraint
módulo a través depip
: pip install python-restricintPara instalar manualmente:
descargar:
$ wget https://pypi.python.org/packages/source/p/python-constraint/python-constraint-1.2.tar.bz2#md5=d58de49c85992493db53fcb59b9a0a45
extracto (Linux / Mac / BSD):
$ bzip2 -cd python-restrictint-1.2.tar.bz2 | tar xvf -
extracto (Windows, con 7zip ):
> 7z e python-restricint-1.2.tar.bz2
> 7z e python-restrictint-1.2.tar
Instalar en pc:
$ cd python-restricint-1.2
$ python setup.py install
fuente
pip install python-constraint
? Lo hice hace un momento y parece dar el resultado esperado.En Prolog, podemos instanciar el dominio simplemente seleccionando elementos de él :) (haciendo elecciones mutuamente excluyentes , para mayor eficiencia). Usando SWI-Prolog,
Se ejecuta al instante:
fuente
Un póster ya mencionó que Prolog es una solución potencial. Esto es cierto, y es la solución que usaría. En términos más generales, este es un problema perfecto para un sistema de inferencia automatizado. Prolog es un lenguaje de programación lógica (y un intérprete asociado) que forman dicho sistema. Básicamente permite la conclusión de hechos de declaraciones hechas usando First Order Logic . FOL es básicamente una forma más avanzada de lógica proposicional. Si decide que no desea usar Prolog, puede usar un sistema similar de su propia creación utilizando una técnica como modus ponens para realizar el saque de conclusiones.
Por supuesto, deberá agregar algunas reglas sobre las cebras, ya que no se menciona en ninguna parte ... Creo que la intención es que pueda descubrir las otras 4 mascotas y deducir que la última es la cebra. Querrás agregar reglas que indiquen que una cebra es una de las mascotas, y cada casa solo puede tener una mascota. Obtener este tipo de conocimiento de "sentido común" en un sistema de inferencia es el principal obstáculo para usar la técnica como una verdadera IA. Hay algunos proyectos de investigación, como Cyc, que intentan dar un conocimiento tan común a través de la fuerza bruta. Se han encontrado con una cantidad interesante de éxito.
fuente
Compatible con SWI-Prolog:
En el intérprete:
fuente
Así es como lo haría. Primero generaría todas las n-tuplas ordenadas
5 ^ 6 de esos, 15625, fácilmente manejables. Luego filtraría las condiciones booleanas simples. hay diez de ellos, y cada uno de ellos esperaría filtrar 8/25 de las condiciones (1/25 de las condiciones contienen un sueco con un perro, 16/25 contienen un no sueco con un no perro) . Por supuesto, no son independientes, pero después de filtrarlos, no deberían quedar muchos.
Después de eso, tienes un buen problema gráfico. Cree un gráfico con cada nodo que represente una de las n-tuplas restantes. Agregue bordes al gráfico si los dos extremos contienen duplicados en alguna posición de n-tupla o violan cualquier restricción 'posicional' (hay cinco de esos). Desde allí, ya casi está en casa, busque en el gráfico un conjunto independiente de cinco nodos (sin que ninguno de los nodos esté conectado por bordes). Si no hay demasiados, posiblemente podría generar exhaustivamente todas las 5 tuplas de n-tuplas y simplemente filtrarlas nuevamente.
Este podría ser un buen candidato para el código de golf. Alguien probablemente pueda resolverlo en una línea con algo como haskell :)
idea de último momento: el paso de filtro inicial también puede eliminar información de las restricciones posicionales. No mucho (1/25), pero sigue siendo significativo.
fuente
Otra solución de Python, esta vez usando PyKE de Python (Python Knowledge Engine). De acuerdo, es más detallado que usar el módulo "restricción" de Python en la solución de @JFSebastian, pero proporciona una comparación interesante para cualquiera que esté buscando un motor de conocimiento en bruto para este tipo de problema.
pistas.kfb
relaciones.krb
driver.py (en realidad más grande, pero esta es la esencia)
Salida de muestra:
Fuente: https://github.com/DreadPirateShawn/pyke-who-owns-zebra
fuente
Aquí hay un extracto de la solución completa usando NSolver , publicado en Einstein's Riddle en C # :
fuente
Aquí hay una solución sencilla en CLP (FD) (ver también clpfd):
Ejecutándolo, produce:
fuente
neighbor(X,Y) :- abs(X-Y) #= 1.
En PAIP (Capítulo 11), Norvig resuelve el acertijo de cebra utilizando un Prólogo incrustado en Lisp .
fuente
Solución ES6 (Javascript)
Con muchos generadores ES6 y un poco de lodash . Necesitarás a Babel para ejecutar esto.
Resultado:
El tiempo de ejecución es de alrededor de 2.5 segundos para mí, pero esto se puede mejorar mucho cambiando el orden de las reglas. Decidí mantener el orden original para mayor claridad.
¡Gracias, este fue un gran desafío!
fuente
Esto es realmente un problema de resolución de restricciones. Puede hacerlo con un tipo generalizado de propagación de restricciones en programación lógica como los lenguajes. Tenemos una demostración específica para el problema de Zebra en el sistema ALE (motor de lógica de atributos):
http://www.cs.toronto.edu/~gpenn/ale.html
Aquí está el enlace a la codificación de un rompecabezas Zebra simplificado:
http://www.cs.toronto.edu/~gpenn/ale/files/grammars/baby.pl
Hacer esto de manera eficiente es otra cuestión.
fuente
La forma más fácil de resolver estos problemas mediante programación es usar bucles anidados en todas las permutaciones y verificar si el resultado satisface los predicados en la pregunta. Muchos de los predicados se pueden izar del bucle interno a los externos para reducir drásticamente la complejidad computacional hasta que la respuesta se pueda calcular en un tiempo razonable.
Aquí hay una solución simple de F # derivada de un artículo en F # Journal :
La salida obtenida en 9 ms es:
fuente
El ejemplo de Microsoft Solver Foundation de: https://msdn.microsoft.com/en-us/library/ff525831%28v=vs.93%29.aspx?f=255&MSPPError=-2147217396
fuente
Esta es una solución MiniZinc para el rompecabezas de cebra como se define en Wikipedia:
Solución:
fuente