I'm trying to solve a version of Einstein's Riddle. Therefore I defined a few rules:
students(Students) :-
length(Students, 6),
member([manuel, _, _, _], Students),
member([tobias, _, pas, _], Students),
member([louise, _, _, _], Students),
member([sophia, _, _, _], Students),
member([hannes, 18, _, _], Students),
member([oliver, _, _, _], Students),
member([_, 18, _, _], Students),
member([_, 19, _, win], Students),
member([_, 20, stu, _], Students),
member([_, 21, _, _], Students),
member([_, 22, _, _], Students),
member([_, 23, _, _], Students),
member([_, _, ulm, _], Students),
member([_, _, fra, _], Students),
member([_, _, pas, _], Students),
member([_, _, hei, inf], Students),
member([_, _, aug, _], Students),
member([_, _, stu, _], Students),
member([_, _, _, win], Students),
member([_, _, _, wig], Students),
member([_, _, _, bwl], Students),
member([_, _, _, inf], Students),
member([_, _, _, gbm], Students),
member([_, _, _, rwi], Students).
As I tested it to see if there are any error so far, I encountered the following output:
?- students(X).
X = [[manuel, 19, ulm, win], [tobias, 21, pas, _1574], [louise, 20, stu, _1604], [sophia, 22, fra, _1634], [hannes, 18, hei, inf], [oliver, 23, aug, _1694]]
X = [[manuel, 19, ulm, win], [tobias, 21, pas, _1350], [louise, 20, stu, _1380], [sophia, 22, fra, _1410], [hannes, 18, hei, inf], [oliver, 23, aug, _1470]]
X = [[manuel, 19, ulm, win], [tobias, 21, pas, _1350], [louise, 20, stu, _1380], [sophia, 22, fra, _1410], [hannes, 18, hei, inf], [oliver, 23, aug, _1470]]
X = [[manuel, 19, ulm, win], [tobias, 21, pas, _1350], [louise, 20, stu, _1380], [sophia, 22, fra, _1410], [hannes, 18, hei, inf], [oliver, 23, aug, _1470]]
...
Since there are more rules needed to solve it completely I was expecting more than one solution. But I'm confused why win
and inf
are used correctly but wig
, bwl
, rwi
and gbm
are not.
Could you explain to me why this happens and how to fix it?
(I don't know if it's just a problem of the dialect. Thus, I tested it on the website https://swish.swi-prolog.org/example/examples.swinb)
You did not specify the domains for the values. As a result all variables can, to some extent, remain free. You can make use of permutation/2
for example to specify that the names are limited to manuel
, tobias
, louise
, sophia
, hannes
, and oliver
:
students(Students) :-
Students = [
[manuel, AA, SA, TA],
[tobias, AB, SB, TB],
[louise, AC, SC, TC],
[sophia, AD, SD, TD],
[hannes, AE, SE, TE],
[oliver, AF, SF, TF]
],
member([tobias, _, pas, _], Students),
member([hannes, 18, _, _], Students),
member([_, 19, _, win], Students),
member([_, 20, stu, _], Students),
member([_, _, hei, inf], Students),
permutation([AA, AB, AC, AD, AE, AF], [18, 19, 20, 21, 22, 23]),
permutation([SA, SB, SC, SD, SE, SF], [ulm, fra, pas, hei, aug, stu]),
permutation([TA, TB, TC, TD, TE, TF], [win, wig, bwl, inf, gbm, rwi]).
We here can set the order of the names already fixed, since there are no predicates like "Manuel is located next to a person with age 20", this is thus a form of symmetry we can remove (or you can use permutation/2
if necessary).
We furthermore do not have to mention any constraints that only restrict domains. We can do that with member/2
, but it would likely be less efficient, and furthermore then we have to fully specify the domain, not only cases like member([hannes, 18, _, _], Students)
, since this makes a connection between hannes who is 18 years old.
This gives us 44'928 solutions, if we allow an arbitrary order of students, we have to multiply this with 4! = 24, so then there are 1'078'272 solutions.