Search code examples
prolog

Underscore followed by numbers instead of solution


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)


Solution

  • 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.