我知道如何在Prolog中迭代列表以找到最大值,但是如果每个东西都是单独的子句呢?例如,如果我有一堆猫科动物和他们的年龄,我怎么能找到最老的小猫?
cat(sassy, 5).
cat(misty, 3).
cat(princess, 2).
我的第一个想法是“嗯,最老的猫是没有老年人存在的猫”。但我无法将其转化为prolog。
oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X \= Y, \+ AgeX < AgeY, print(Y).
这仍然错误地匹配“有雾”。这样做的正确方法是什么?有没有什么方法可以更直接地迭代年龄来选择最大值?
答案 0 :(得分:6)
一种方法是
oldest(X) :- cat(X, AgeX), \+ Y^(cat(Y, AgeY), Y \= X, AgeX < AgeY).
您还可以使用setof / 3获取所有猫的列表并从中获得最大值。
答案 1 :(得分: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.
答案 2 :(得分:2)
这是一个循环遍历所有解决方案的解决方案,始终记录比以前更好的解决方案。最后,返回最佳解决方案。
录制是使用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是典型的爱沙尼亚猫名。 ;)
答案 3 :(得分:0)
在风格上 - 这里有一些不同的方法(一些非常优雅,另一些更“可读”)。如果你是一个初学者 - 选择你自己的,首选的做事方式 - 无论多么低效。
您可以稍后学习提高效率的技巧。享受Prolog-它是一种美丽的语言。
答案 4 :(得分:-2)
我不太记得Prolog,但我知道你不应该像使用命令式编程语言那样考虑解决问题。