El acertijo de la cebra
Hoy vamos a resolver un acertijo bastante famoso, el de la cebra, atribuido a Einstein y a Lewis Carroll. Seguramente no haya sido inventado por ninguno de los dos, pero sigue siendo muy interesante.
El puzzle dice lo siguiente:
- Cinco hombres de cinco nacionalidades diferentes viven en las primeras cinco casas de una calle. Tienen cinco profesiones diferentes y cada uno tiene un animal y una bebida favorita diferentes. Cada casa está pintada de un color diferente.
- El inglés vive en la casa roja.
- El español tiene un perro.
- El japonés es pintor.
- El italiano bebe té.
- El noruego vive en la primera casa por la izquierda.
- El dueño de la casa verde bebe café.
- La casa verde está a la derecha de la casa blanca.
- El escultor cultiva caracoles.
- El diplomático vive en la casa amarilla.
- La leche se bebe en la casa de enmedio.
- La casa del noruego está al lado de la casa azul.
- El violinista bebe zumo de frutas.
- El zorro está en una casa al lado de la del doctor.
- El caballo está en una casa al lado de la del diplomático.
¿Quién tiene una cebra? ¿Quién bebe agua?
Resolviéndolo usando clpz
Usando clpz podemos resolver este acertijo de forma muy clara y concisa. El truco consista en asignar un número a cada casa, en orden, siendo el 1 la casa más a la izquierda y 5 la casa a la derecha. Sobre eso, creamos variables para cada una de las nacionalidad, profesiones, bebidas, etc que podrán adquirir un valor entre 1 y 5. Por supuesto, dentro de cada categoría, no se pueden repetir los números, porque cada uno está asignado a una casa diferente.
Vars = [
% nationalities
English, Spanish, Japanese, Norwegian, Italian,
% professiones
Painter, Doctor, Diplomat, Violinist, Sculptor,
% beverages
Tea, Coffee, Juice, Milk, Water,
% colors
Red, Green, White, Yellow, Blue,
% animals
Dog, Snails, Fox, Horse, Zebra],
Vars ins 1..5,
all_different([English, Spanish, Japanese, Norwegian, Italian]),
all_different([Painter, Doctor, Diplomat, Violinist, Sculptor]),
all_different([Tea, Coffee, Juice, Milk, Water]),
all_different([Red, Green, White, Yellow, Blue]),
all_different([Dog, Snails, Fox, Horse, Zebra]),
A continuación codificamos las reglas. Como asignamos el valor en base a la posición de la casa, una casa a la derecha de otra es simplemente sumar 1. Decir que una casa está al lado de otra, significa que la diferencia absoluta entre 2 variables tiene que ser 1.
English #= Red,
Spanish #= Dog,
Japanese #= Painter,
Italian #= Tea,
Norwegian #= 1,
Green #= Coffee,
Green #= White + 1,
Sculptor #= Snails,
Diplomat #= Yellow,
Milk #= 3,
abs(Norwegian-Blue) #= 1,
Violinist #= Juice,
abs(Fox-Doctor) #= 1,
abs(Horse-Diplomat) #= 1,
Si juntamos todo, nos dará el siguiente programa, ya bonito para ver el resultado.
:- use_module(library(clpz)).
:- use_module(library(lists)).
:- use_module(library(format)).
run :-
zebra(Vars),
append([English,Spanish,Japanese,Norwegian,Italian|_], [Zebra], Vars),
Nats = [English-english, Spanish-spanish, Japanese-japanese, Norwegian-norwegian, Italian-italian],
member(Zebra-Nat, Nats),
format("The ~a has the zebra~n", [Nat]),
nth0(14, Vars, Water),
member(Water-Nat1, Nats),
format("The ~a has the water~n", [Nat1]).
zebra(Vars) :-
Vars = [
% nationalities
English, Spanish, Japanese, Norwegian, Italian,
% professiones
Painter, Doctor, Diplomat, Violinist, Sculptor,
% beverages
Tea, Coffee, Juice, Milk, Water,
% colors
Red, Green, White, Yellow, Blue,
% animals
Dog, Snails, Fox, Horse, Zebra],
Vars ins 1..5,
all_different([English, Spanish, Japanese, Norwegian, Italian]),
all_different([Painter, Doctor, Diplomat, Violinist, Sculptor]),
all_different([Tea, Coffee, Juice, Milk, Water]),
all_different([Red, Green, White, Yellow, Blue]),
all_different([Dog, Snails, Fox, Horse, Zebra]),
English #= Red,
Spanish #= Dog,
Japanese #= Painter,
Italian #= Tea,
Norwegian #= 1,
Green #= Coffee,
Green #= White + 1,
Sculptor #= Snails,
Diplomat #= Yellow,
Milk #= 3,
abs(Norwegian-Blue) #= 1,
Violinist #= Juice,
abs(Fox-Doctor) #= 1,
abs(Horse-Diplomat) #= 1,
label(Vars).
El resultado es que la cebra la tenía el japonés y el noruego es el que bebe agua.