English 中文(简体)
Max out of values defined by prolog clauses
原标题:
  • 时间:2009-11-09 15:20:14
  •  标签:
  • prolog

I know how to iterate over lists in Prolog to find the maximum, but what if each thing is a separate clause? For example if I had a bunch of felines and their ages, how would I find the oldest kitty?

cat(sassy, 5).
cat(misty, 3).
cat(princess, 2).

My first thought was "hmm, the oldest cat is the one for which no older exists". But I couldn t really translate that well to prolog.

oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X = Y, + AgeX < AgeY, print(Y).

This still errorenously matches "misty". What s the proper way to do this? Is there some way to more directly just iterate over the ages to choose max?

最佳回答

A cat is the oldest if it s a cat and there is not a cat older than it. Let s write that in Prolog:

oldest(X):- cat(X, _), not( thereAreOlders(X)), !.
thereAreOlders(X):- cat(X, N), cat(C, M), C=X, M > N.

If you consult:

?- oldest(X).
X = sassy.
问题回答

One way is

oldest(X) :- cat(X, AgeX), + Y^(cat(Y, AgeY), Y = X, AgeX < AgeY).

You can also use setof/3 to get a list of all cats and get the maximum from that.

Here is a solution that loops through all the solutions, always recording the solution that is better than the previous best. In the end, the best solution is returned.

The recording is done using assert/1, you could also use a non-backtrackable global variable if your Prolog provides that (SWI-Prolog does).

The benefit of this approach is that is considers each solution only once, i.e. complexity O(n). So, even though it looks uglier than starblue s solution, it should run better.

% Data
cat(sassy, 5).
cat(misty, 3).
cat(miisu, 10).
cat(princess, 2).

% Interface
oldest_cat(Name) :-
    loop_through_cats,
    fetch_oldest_cat(Name).

loop_through_cats :-
    cat(Name, Age),
    record_cat_age(Name, Age),
    fail ; true.


:- dynamic current_oldest_cat/2.

record_cat_age(Name, Age) :-
    current_oldest_cat(_, CAge),
    !,
    Age > CAge,
    retract(current_oldest_cat(_, _)),
    assert(current_oldest_cat(Name, Age)).

record_cat_age(Name, Age) :-
    assert(current_oldest_cat(Name, Age)).


fetch_oldest_cat(Name) :-
    retract(current_oldest_cat(Name, _Age)).

Usage example:

?- oldest_cat(Name).

Name = miisu

Miisu is a typical Estonian cat name. ;)

On a stylistic point- there are a few different approaches here (some are very elegant, others more readable ). If you re a beginner- chose your own, preferred, way of doing things- however inefficient.

You can learn techniques for efficiency later. Enjoy Prolog- its a beautiful language.

I don t remember much Prolog, but I do know that you shouldn t think about solving problems as you would with an imperative programming language.





相关问题
Prolog : Learning by example

I am trying to learn a little bit about swi-prolog (beyond the basic, useless programs). Can anyone explain (perhaps in pseudocode) what this sudoku solver and the related functions are doing? If ...

Working with lists in Prolog

First off let me state that this is part of a class exercise given as homework. But, the entire assignment is much more involved than the subject of this question. So.. I am searching through two ...

SWI-Prolog conditional statements

I m trying to write a function that will test to see if the word hello is contained in a list. If it is contained, i don t want it to say "true", i want it to say : "yes, the word hello is contained ...

prolog cut off in method

I have a question I would like to ask you something about a code snippet: insert_pq(State, [], [State]) :- !. insert_pq(State, [H|Tail], [State, H|Tail]) :- precedes(State, H). insert_pq(State, [...

Max out of values defined by prolog clauses

I know how to iterate over lists in Prolog to find the maximum, but what if each thing is a separate clause? For example if I had a bunch of felines and their ages, how would I find the oldest kitty? ...

热门标签