Unsure of why code snippet works/what it's doing with logic riddle

259 views Asked by At

I was looking through some prolog examples and stumbled upon http://www.anselm.edu/internet/compsci/faculty_staff/mmalita/HOMEPAGE/logic/bufalo.txt

first_names([keith,libby,margo,nora,otto]).
last_names([fell,grant,hall,ivey,jule]).
ages([2,3,4,5,6]).

start(Sol):- first_names(F),last_names(L),ages(A),
         Sol=[[F1,L1,A1],[F2,L2,A2],[F3,L3,A3],[F4,L4,A4],[F5,L5,A5]],
                F=[F1,F2,F3,F4,F5],             % if order is not important!
        member([libby,jule,_],Sol), % 1
        set_equal([L1,L2,L3,L4,L5],L),  % write correspondence
        set_equal([A1,A2,A3,A4,A5],A),
                member([keith,_,AgeK],Sol),     % 2
        member([_,ivey,AgeI],Sol),AgeK is AgeI+1,
        member([nora,_,AgeN],Sol),AgeI is AgeN+1,
        member([margo,_,AgeM],Sol),
        member([_,fell,AgeF],Sol),AgeF is 3+AgeM,
        member([otto,_,AgeO],Sol),member([_,hall,AgeH],Sol).

In this code example I have a general idea of how it works, but I'm really not sure on the specifics

I understand defining the hints as a list of atoms with the first field being first name, second field being last name, and third field being age with underscores showing missing information. However I'm not really sure why this is being called with member onto the Sol array. Not sure what it does in this context

Additionally, I don't really understand the purpose of the set_equal's and the F= in this code. It seems like it's setting three variables which are not referenced at all?

Thanks for your help!

1

There are 1 answers

2
CapelliC On BEST ANSWER

I've downloaded the code from the link you provide, to test with SWI-Prolog: there are a couple of syntactic problems in bibmm.pl, and at least set_equal/3 must change to:

set_equal([H|T],R):- member(H,R),select(H,R,Rez),set_equal(T,Rez).

After the correction, it does produce:

?- start(X).
X = [[keith, fell, 5], [libby, jule, 6], [margo, grant, 2], [nora, hall, 3], [otto, ivey, 4]] ;
X = [[keith, fell, 6], [libby, jule, 2], [margo, grant, 3], [nora, hall, 4], [otto, ivey, 5]] ;
X = [[keith, fell, 5], [libby, jule, 6], [margo, hall, 2], [nora, grant, 3], [otto, ivey, 4]] ;
X = [[keith, fell, 6], [libby, jule, 2], [margo, hall, 3], [nora, grant, 4], [otto, ivey, 5]] ;
X = [[keith, grant, 4], [libby, jule, 5], [margo, ivey, 3], [nora, hall, 2], [otto, fell, 6]] ;
X = [[keith, hall, 4], [libby, jule, 5], [margo, ivey, 3], [nora, grant, 2], [otto, fell, 6]] ;
false.

Now,

why this is being called with member onto the Sol array

member/2 will bind slots to to acceptable values, so the partially specified rows will get temptative values, and Prolog' backtracking will provide the search of appropriate permutations, that, as stated in bibmm.pl, are generated by set_equal/2.

About F=[...], I think it's just an aesthetic choice of the author, since F it's not used anymore in the start/1 procedure. Could be written as well as

start(Sol):- first_names([F1,F2,F3,F4,F5]),last_names(L),ages(A),
...

edit I didn't noticed, but there is a bug, namely, missing last constraint. After adding it

...
member([otto,_,AgeO],Sol),member([_,hall,AgeH],Sol),
AgeO is AgeH * 2.

the result is arguably better

?- start(X).
X = [[keith, fell, 5], [libby, jule, 6], [margo, hall, 2], [nora, grant, 3], [otto, ivey, 4]]