1

我知道如何遍历 Prolog 中的列表以找到最大值,但是如果每件事都是一个单独的子句怎么办?例如,如果我有一群猫科动物和它们的年龄,我将如何找到最古老的小猫?

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

我的第一个想法是“嗯,最老的猫是没有更老的猫”。但我不能很好地翻译成序言。

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

这仍然错误地匹配“朦胧”。这样做的正确方法是什么?有没有办法更直接地迭代年龄来选择最大值?

4

5 回答 5

6

一种方法是

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

您还可以使用 setof/3 获取所有猫的列表并从中获得最大值。

于 2009-11-09T21:04:54.060 回答
4

如果猫是猫并且没有比它大的猫,那么它就是最老的猫。让我们在 Prolog 中这样写:

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

如果您咨询:

?- oldest(X).
X = sassy.
于 2009-11-10T02:12:35.157 回答
1

这是一个循环遍历所有解决方案的解决方案,始终记录比以前最好的解决方案。最后,返回最佳解决方案。

记录是使用 完成的assert/1,如果您的 Prolog 提供(SWI-Prolog 提供),您也可以使用不可回溯的全局变量。

这种方法的好处是每个解决方案只考虑一次,即复杂度 O(n)。因此,即使它看起来比 starblue 的解决方案丑,它也应该运行得更好。

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

使用示例:

?- oldest_cat(Name).

Name = miisu

Miisu是典型的爱沙尼亚猫名。;)

于 2009-11-10T09:30:55.790 回答
0

在风格上——这里有几种不同的方法(一些非常优雅,另一些更“可读”)。如果您是初学者 - 选择自己喜欢的做事方式 - 但效率低下。

您可以稍后学习提高效率的技术。享受 Prolog - 它是一种美丽的语言。

于 2013-03-26T17:14:28.130 回答
-2

我不记得太多 Prolog,但我知道您不应该像使用命令式编程语言那样考虑解决问题。

于 2009-11-09T21:31:00.600 回答