0
votes

I'm working on a simple program that has a database of people. When given a year it should state the "King" of that year, where the king is the eldest living man.

For simplicity, all people in the database are eligible as long as they are alive at the given year and I'm assuming there are no twins.

My problem is picking the "oldest" person alive during a given year. I can't seem to figure out how to ask Prolog to examine all possible kings and pick the oldest.


male(jack).
male(roy).
male(ele).


born(jack,2000).

born(dave,1999).
born(roy,1980).
born(ele,1990).

died(jack, 2100).
died(dave, 2099).
died(roy, 1990).
died(ele, 1999).


% compare X against all other possibleSuccessors and make sure he was born 1st.

eldest(X,Year):-
    born(X,T1),
    born((possibleSuccessor(Year,_)),T2),
    T1 < T2.

% must be male and have been born before or during the given year and must not be dead.

possibleSuccessor(Year, X):-
    male(X),
    born(X,B),
    died(X,D),
    (B =< Year),
    (D >= Year).


successor(Year):-
    possibleSuccessor(Year,X),
    eldest(X,Year),
    write(X).

Any help on comparing all possible answers vs one another would be appreciated. I attempted to use findall before but was unsuccessful.

1
The expression born((posibleSuccessor(Year,_)), T2) doesn't do what you think it does. Prolog doesn't have functions that return values. It has predicates that are used to query and instantiate arguments. So the expression will always fail since there are no born/2 fact or predicate that matches born((possibleSuccessor(...)), ...). - lurker

1 Answers

0
votes

Prolog offers a restricted form of negation (negation by failure) that solve your problem:

eldest(X,Year):-
    born(X,Year),
    \+((born(_,T), T<Year)).

this says that X is eldest if we can't find any other born before him.

alternatively, setof/3 can be used:

eldest(X,Year):-
    setof((Y,K), born(K,Y), [(Year,X)|_]).

this works sorting all pairs (Y,K), then we can pick just the head of the result.

edit this should solve the problem, but I've introduced a service predicate

eldest(X, Year):-
    alive(X, Year, B),
    \+((alive(_, Year, T), T<B)).

alive(X, Year, B) :- born(X, B), B =< Year, \+ (died(X, D), D < Year).

% must be male and have been born before or durring the given year and must not be dead.

possibleSuccessor(Year,X):-
    male(X),
    alive(X, Year, _).

successor(Year):-
    possibleSuccessor(Year,X),
    eldest(X,Year),
    write(X).