Max out of values defined by prolog clauses

前端 未结 5 858
名媛妹妹
名媛妹妹 2021-01-01 07:41

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 woul

相关标签:
5条回答
  • 2021-01-01 08:11

    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.

    0 讨论(0)
  • 2021-01-01 08:25

    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.
    
    0 讨论(0)
  • 2021-01-01 08:26

    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.

    0 讨论(0)
  • 2021-01-01 08:27

    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.

    0 讨论(0)
  • 2021-01-01 08:31

    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. ;)

    0 讨论(0)
提交回复
热议问题