How to do only 2 recursive calls in Prolog?

Viewed 81
isTallerThan2(X,Y) :- tallerThan(X,Y).
isTallerThan2(X,Y) :- tallerThan(X,Z), isTallerThan2(Z,Y).

Where I want to find where someone is taller than 2 people.

If I have lots of relations where person X is taller than person Y like this tallerThan(X,Y)and if person b is taller than person a and person c is taller than person b... then I want to find all persons c but stop there and not find persons d,e,f... etc.

2 Answers

Since you have your database of tallerThan/2 facts, and you trust it (that is, tallerThan/2 is a DAG), you can write your rule as simple as

isTallerThan2(X,_Y) :- tallerThan(X,A),tallerThan(X,B),A\==B.

As per your comment, the second argument isn't used, so better to write like

isTallerThan2(X) :- tallerThan(X,A),tallerThan(X,B),A\==B.
isTallerThan2(X,_Y) :- isTallerThan2(X).

Since you are not interested in the smaller Persons, you need to store only the larger person. There are two ways to build it: one is to hardcode two relations, the other one is to recursively code it with a counter variable.

Version one: Z is taller than Y, Y is taller than someone.

tallerThan2(Z):- 
    tallerThan(Y,_), 
    tallerThan(Z,Y).

For the fact base

tallerThan(marge, homer).
tallerThan(homer, bart).
tallerThan(bart, lisa).
tallerThan(lisa, maggie).
tallerThan(abe, maggie).
tallerThan(marge, abe).

the output is

?- tallerThan2(P).
P = marge ;
P = homer ;
P = bart ;
P = marge ;
false.

The second way is to count the number of relations. You know of person Y that he or she is taller as at least NN people. If person Z is taller than Y then Z is taller than at least N = NN+1 people.

taller(Y,1) :- 
    tallerThan(Y,_).
taller(Z,N) :- 
    tallerThan(Z,Y), 
    taller(Y,NN),
    N is NN+1.

Now the test:

?- taller(P,2).
P = marge ;
P = homer ;
P = bart ;
P = marge ;
false.

Is the same. marge appears twice in the list since she is taller than homer and taller than abe; both are taller than maggie.

Related