1

I'm making the Einstein's Riddle, I have a solution but I don't understand how works one specific statement, here is the code:

zebra_owner(Owner) :-
    houses(Hs),
    member(h(Owner,zebra,_,_,_), Hs).

water_drinker(Drinker) :-
    houses(Hs),
    member(h(Drinker,_,_,water,_), Hs).

houses(Hs) :-
    % each house in the list Hs of houses is represented as:
    %      h(Nationality, Pet, Cigarette, Drink, Color)
    length(Hs, 5),                                            %  1
    member(h(english,_,_,_,red), Hs),                         %  2
    member(h(spanish,dog,_,_,_), Hs),                         %  3
    member(h(_,_,_,coffee,green), Hs),                        %  4
    member(h(ukrainian,_,_,tea,_), Hs),                       %  5
    next(h(_,_,_,_,green), h(_,_,_,_,white), Hs),             %  6
    member(h(_,snake,winston,_,_), Hs),                       %  7
    member(h(_,_,kool,_,yellow), Hs),                         %  8
    Hs = [_,_,h(_,_,_,milk,_),_,_],                           %  9
    Hs = [h(norwegian,_,_,_,_)|_],                            % 10
    next(h(_,fox,_,_,_), h(_,_,chesterfield,_,_), Hs),        % 11
    next(h(_,_,kool,_,_), h(_,horse,_,_,_), Hs),              % 12
    member(h(_,_,lucky,juice,_), Hs),                         % 13
    member(h(japanese,_,kent,_,_), Hs),                       % 14
    next(h(norwegian,_,_,_,_), h(_,_,_,_,blue), Hs),          % 15
    member(h(_,_,_,water,_), Hs),       % one of them drinks water
    member(h(_,zebra,_,_,_), Hs).       % one of them owns a zebra

next(A, B, Ls) :- append(_, [A,B|_], Ls).
next(A, B, Ls) :- append(_, [B,A|_], Ls).

The last part where the next is, I understand what it refers to, they are used to say that a house is next to another, but I do not understand how can the same function use two things in reverse to one another, how does Prolog know when to use one or the other? maybe I am forgetting some of this logical language but I don't remember right now and that is my doubt. I want to understand how it works.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • It doesn't, it just backtracks in case it results in inconsistency. – Willem Van Onsem May 29 '20 at 23:48
  • @Oscar yes, the two clauses of the `next/3` predicate definition form an implicit *disjunction*, i.e. a (Non-exclusive) OR combination. this could also be written as one clause `next(A, B, Ls) :- append(_, [A,B|_], Ls) ; append(_, [B,A|_], Ls).` instead. --- as, in logic, `A \/ B` is true if `A` is true, or if `B` is true (or both), so does in Prolog `A ; B` succeed if `A` succeeds, or if `B` succeeds (or both). IOW after we've explored all the solutions of `A ; B`, we will have collected all solutions from `A`, and also, independently, all the solutions from `B`. – Will Ness May 30 '20 at 17:32
  • 1
    so, `next(A, B, Ls)` succeeds if `[A,B]` is somewhere inside `Ls`, *or* if `[B,A]` is somewhere inside `Ls`. – Will Ness May 30 '20 at 17:37

0 Answers0