Edit: this puzzle is also known as "Einstein's Riddle"
The Who owns the Zebra (you can try the online version here) is an example of a classic set of puzzles and I bet that most people on Stack Overflow can solve it with pen and paper. But what would a programmatic solution look like?
Based on the clues listed below...
- There are five houses.
- Each house has its own unique color.
- All house owners are of different nationalities.
- They all have different pets.
- They all drink different drinks.
- They all smoke different cigarettes.
- The English man lives in the red house.
- The Swede has a dog.
- The Dane drinks tea.
- The green house is on the left side of the white house.
- They drink coffee in the green house.
- The man who smokes Pall Mall has birds.
- In the yellow house they smoke Dunhill.
- In the middle house they drink milk.
- The Norwegian lives in the first house.
- The man who smokes Blend lives in the house next to the house with cats.
- In the house next to the house where they have a horse, they smoke Dunhill.
- The man who smokes Blue Master drinks beer.
- The German smokes Prince.
- The Norwegian lives next to the blue house.
- They drink water in the house next to the house where they smoke Blend.
...who owns the Zebra?
The Microsoft Solver Foundation example from: https://msdn.microsoft.com/en-us/library/ff525831%28v=vs.93%29.aspx?f=255&MSPPError=-2147217396
In Prolog, we can instantiate the domain just by selecting elements from it :) (making mutually-exclusive choices, for efficiency). Using SWI-Prolog,
Runs quite instantly:
Here is a straightforward solution in CLP(FD) (see also clpfd):
Running it, produces:
Here's a solution in Python based on constraint-programming:
Output:
It takes 0.6 seconds (CPU 1.5GHz) to find the solution.
The answer is "German owns zebra."
To install the
constraint
module viapip
: pip install python-constraintTo install manually:
download:
$ wget https://pypi.python.org/packages/source/p/python-constraint/python-constraint-1.2.tar.bz2#md5=d58de49c85992493db53fcb59b9a0a45
extract (Linux/Mac/BSD):
$ bzip2 -cd python-constraint-1.2.tar.bz2 | tar xvf -
extract (Windows, with 7zip):
> 7z e python-constraint-1.2.tar.bz2
> 7z e python-constraint-1.2.tar
install:
$ cd python-constraint-1.2
$ python setup.py install
Here's how I'd go about it. First I'd generate all the ordered n-tuples
5^6 of those, 15625, easily manageable. Then I'd filter out the simple boolean conditions. there's ten of them, and each of those you'd expect to filter out 8/25 of the conditions (1/25 of the conditions contain a Swede with a dog, 16/25 contain a non-Swede with a non-dog). Of course they're not independent but after filtering those out there shouldn't be many left.
After that, you've got a nice graph problem. Create a graph with each node representing one of the remaining n-tuples. Add edges to the graph if the two ends contain duplicates in some n-tuple position or violate any 'positional' constraints (there's five of those). From there you're almost home, search the graph for an independent set of five nodes (with none of the nodes connected by edges). If there's not too many, you could possibly just exhaustively generate all the 5-tuples of n-tuples and just filter them again.
This could be a good candidate for code golf. Someone can probably solve it in one line with something like haskell :)
afterthought: The initial filter pass can also eliminate information from the positional constraints. Not much (1/25), but still significant.
One poster already mentioned that Prolog is a potential solution. This is true, and it's the solution I would use. In more general terms, this is a perfect problem for an automated inference system. Prolog is a logic programming language (and associated interpreter) that form such a system. It basically allows concluding of facts from statements made using First Order Logic. FOL is basically a more advanced form of propositional logic. If you decide you don't want to use Prolog, you could use a similar system of your own creation using a technique such as modus ponens to perform the draw the conclusions.
You will, of course, need to add some rules about zebras, since it isn't mentioned anywhere... I believe the intent is that you can figure out the other 4 pets and thus deduce the last one is the zebra? You'll want to add rules that state a zebra is one of the pets, and each house can only have one pet. Getting this kind of "common sense" knowledge into an inference system is the major hurdle to using the technique as a true AI. There are some research projects, such as Cyc, which are attempting to give such common knowledge through brute force. They've met with an interesting amount of success.