如果多次出现相同的结果,如何不显示 - Prolog
How not to show if there is same result occurs more than once- Prolog
场景
我有如下代码。我的问题是如何不多次显示相同的结果。
male(charles).
male(andrew).
male(edward).
female(ann).
age(charles, 70).
age(ann, 65).
age(andrew, 60).
age(edward, 55).
nextking(X) :- age(X,P), age(Y,Q),
P>=Q, X\==Y; age(X,55).
当前输出
我需要的
我需要输出为 charles, ann, andrew, edward。没有重复的名字。
对于相当新的版本,您可以使用库(solution_sequences):
?- distinct(nextking(X)).
X = charles ;
X = ann ;
X = andrew ;
X = edward.
或使用经典的 'all solutions' 内置函数:
?- setof(K,K^nextking(K),Ks),member(X,Ks).
Ks = [andrew, ann, charles, edward],
X = andrew ;
Ks = [andrew, ann, charles, edward],
X = ann ;
...
但在这种情况下,我们放宽了 KB 定义的回答顺序。
你的nextking/1
谓词效率很低,而且不能保证按年龄排序。
例如,如果我们将 charles
放在事实列表的最后,我们将得到:
?- nextking(X).
X = ann ;
X = ann ;
X = andrew ;
X = charles ;
X = charles ;
X = charles ;
X = edward.
基本上你写的谓词有两个子句:
nextking(X) :-
age(X,P),
age(Y,Q),
P >= Q,
X\==Y.
nextking(X) :-
age(X, 55).
第一个简单地产生任何X
,其中存在一个更年轻的人Y
。但这并不能保证这些元素是有序的。最后一个谓词将统一所有 55 岁的人 X
。对于这个特定的案例,这是可行的,但这意味着如果我们陈述另一个事实 age(louise, 14)
,那么这将失败。这种方法不仅不正确,而且即使是正确的也会非常"unstable".
我们可以利用 setof/3
[swi-doc] 谓词,它不仅可以执行唯一性过滤器,还可以对元素进行排序。
既然我们要按照年龄降序对皇室成员进行排序,那么我们应该构建二元组(或封装两个参数的其他结构),其中第一个参数包含 negative 年龄,第二个参数对应的人。
然后我们可以使用member/2
[swi-doc]到"unwind"单独统一的列表:
nextking(X) :-
setof((NA, X), A^(age(X, A), NA is -A), Royals),
member((_, X), Royals).
这将生成如下元素列表:
?- nextking(X).
X = charles ;
X = ann ;
X = andrew ;
X = edward.
无论源文件中的事实如何排序。
场景
我有如下代码。我的问题是如何不多次显示相同的结果。
male(charles).
male(andrew).
male(edward).
female(ann).
age(charles, 70).
age(ann, 65).
age(andrew, 60).
age(edward, 55).
nextking(X) :- age(X,P), age(Y,Q),
P>=Q, X\==Y; age(X,55).
当前输出
我需要的
我需要输出为 charles, ann, andrew, edward。没有重复的名字。
对于相当新的版本,您可以使用库(solution_sequences):
?- distinct(nextking(X)).
X = charles ;
X = ann ;
X = andrew ;
X = edward.
或使用经典的 'all solutions' 内置函数:
?- setof(K,K^nextking(K),Ks),member(X,Ks).
Ks = [andrew, ann, charles, edward],
X = andrew ;
Ks = [andrew, ann, charles, edward],
X = ann ;
...
但在这种情况下,我们放宽了 KB 定义的回答顺序。
你的nextking/1
谓词效率很低,而且不能保证按年龄排序。
例如,如果我们将 charles
放在事实列表的最后,我们将得到:
?- nextking(X).
X = ann ;
X = ann ;
X = andrew ;
X = charles ;
X = charles ;
X = charles ;
X = edward.
基本上你写的谓词有两个子句:
nextking(X) :-
age(X,P),
age(Y,Q),
P >= Q,
X\==Y.
nextking(X) :-
age(X, 55).
第一个简单地产生任何X
,其中存在一个更年轻的人Y
。但这并不能保证这些元素是有序的。最后一个谓词将统一所有 55 岁的人 X
。对于这个特定的案例,这是可行的,但这意味着如果我们陈述另一个事实 age(louise, 14)
,那么这将失败。这种方法不仅不正确,而且即使是正确的也会非常"unstable".
我们可以利用 setof/3
[swi-doc] 谓词,它不仅可以执行唯一性过滤器,还可以对元素进行排序。
既然我们要按照年龄降序对皇室成员进行排序,那么我们应该构建二元组(或封装两个参数的其他结构),其中第一个参数包含 negative 年龄,第二个参数对应的人。
然后我们可以使用member/2
[swi-doc]到"unwind"单独统一的列表:
nextking(X) :-
setof((NA, X), A^(age(X, A), NA is -A), Royals),
member((_, X), Royals).
这将生成如下元素列表:
?- nextking(X).
X = charles ;
X = ann ;
X = andrew ;
X = edward.
无论源文件中的事实如何排序。