Search code examples
prologduplicatespredicatemeta-predicate

Prolog check for duplicates in answer to query (easy way?)


This is a terrible example, but say I have points a, b and c and blue and red lines, e.g. line(blue,a) means point a lines on a blue line.

point(a).
point(b).
point(c).

line(blue,a).
line(blue,b).
line(red,a).
line(red,c).

I want to find out which points P lie on more than one line (so a in this case as it's on the blue and red line).

I made a start and got this:

multiple_points(P) :- point(P), point(_,P).

When I run the query ?- multiple_points(P). all points that are on a line appear, but I only want duplicates shown to see which points appear on more than one line.

Is there an easy one line way to only show values of P which are duplicates?


Solution

  • The approach is simple to find all the points that lie on the coloured lines. Then find which points occurs multiple times.

    point(a).
    point(b).
    point(c).
    
    line(blue,a).
    line(blue,b).
    line(red,a).
    line(red,c).
    
    points(Z):- findall(X,(line(_,X)) ,Z).
    
    multi([],[]):- !.
    multi([H|T],[H|Z]):- member(H,T) , multi(T,Z),!.
    multi([H|T],Z):- \+member(H,T) , multi(T,Z),!.
    
    
    get_points(List):- points(Z) , multi(Z,List).
    

    OUTPUT

    ?- get_points(List).
       List = [a]
    

    It will work even when you have multiple points that lie on multiple lines.

    lets your knowledge base is

    line(blue,a).
    line(blue,b).
    line(red,a).
    line(red,c).
    line(purple,c).
    

    The output for this instance is

    OUTPUT

    ?- get_points(List).
       List = [a,c]
    

    If no point exists on multiple lines the output would be an empty list List= [].

    Hope this helped you.