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?
Here is an excerpt from the full solution using NSolver, posted at Einstein’s Riddle in C#:
This is really a constraint solving problem. You can do it with a generalized kind of constraint propagation in logic-programming like languages. We have a demo specifically for the Zebra problem in the ALE (attribute logic engine) system:
http://www.cs.toronto.edu/~gpenn/ale.html
Here's the link to the coding of a simplified Zebra puzzle:
http://www.cs.toronto.edu/~gpenn/ale/files/grammars/baby.pl
To do this efficiently is another matter.
SWI-Prolog compatible:
At the interpreter:
ES6 (Javascript) solution
With lots of ES6 generators and a little bit of lodash. You will need Babel to run this.
Result:
Run time is around 2.5s for me, but this can be improved a lot by changing the order of rules. I decided to keep the original order for clarity.
Thanks, this was a cool challenge!
In PAIP (Chapter 11), Norvig solves the zebra puzzle using a Prolog embedded in Lisp.
The easiest way to solve such problems programmatically is to use nested loops over all permutations and check to see if the result satisfies the predicates in the question. Many of the predicates can be hoisted from the inner loop to outer loops in order to dramatically reduce the computational complexity until the answer can be computed in a reasonable time.
Here is a simple F# solution derived from an article in the F# Journal:
The output obtained in 9ms is: