0
votes

I am struggling to work out why this isn't working. Using SWI-Prolog, I am trying to:

  1. Use the people(List) rule to create a list (called List) of females' names from the female (name, eee) facts.
  2. Use the duplicate(List, Element) rule to find any duplicate names in the list generated by people(List)

Both the people and duplicate rules work well on their own, but when I try to combine them the program always returns false when in the case of using carol, should return true.

female(carol,eee).
female(clare,eee).
female(mel,eee).
female(grace,eee).
female(clare,eee).
female(carol,eee).


%% duplicate(List, Element) is true for every matching pair of _Element_ in _List_
duplicate([First|Rest], Element) :-
    duplicate_1(Rest, First, Element).

% First occurrence
duplicate_1([This|Rest], X, X) :- % first occurrence
    duplicate_2(Rest, This, X).
duplicate_1([This|Rest], _, X) :- % look further for first occurrence
    duplicate_1(Rest, This, X).

% Second occurrence
duplicate_2(_, X, X). % second occurrence
duplicate_2([This|Rest], _, X) :- % look further for second occurrence
    duplicate_2(Rest, This, X).


people(List) :- findall(X, female(X,eee), List).

I am trying to enter into terminal:

?- people(Y), duplicate(Y, carol).

Any help would be much appreciated!

1

1 Answers

2
votes

You need to stop recursive calls after you found a duplicate:

female(carol,eee).
female(clare,eee).
female(mel,eee).
female(grace,eee).
female(clare,eee).
female(carol,eee).


%% duplicate(List, Element) is true for every matching pair of _Element_ in _List_
duplicate([First|Rest], Element) :-
    duplicate_1(Rest, First, Element).

% First occurrence
duplicate_1([This|Rest], X, X) :- % first occurrence
    duplicate_2(Rest, This, X), !.
duplicate_1([This|Rest], _, X) :- % look further for first occurrence
    duplicate_1(Rest, This, X).

% Second occurrence
duplicate_2(_, X, X):-!. % second occurrence
duplicate_2([This|Rest], _, X) :- % look further for second occurrence
    duplicate_2(Rest, This, X).


people(List) :- findall(X, female(X,eee), List).

Read about (!) cut.