如何不显示是否出现相同的结果多次-Prolog

时间:2018-10-31 01:27:11

标签: prolog swi-prolog

场景

我有以下代码。我的问题是如何不多次出现相同的结果。

let foo = {
  bar: function() {
    console.log('foo.bar()');
  }
};

当前输出

enter image description here

我需要的

我需要输出为Charles,Ann,Andrew,Edward。没有名字重复。

2 个答案:

答案 0 :(得分:4)

在相当新的版本中,您可以使用库(solution_sequences):

?- distinct(nextking(X)).
X = charles ;
X = ann ;
X = andrew ;
X = edward.

或使用内置的经典“所有解决方案”:

?- setof(K,K^nextking(K),Ks),member(X,Ks).
Ks = [andrew, ann, charles, edward],
X = andrew ;
Ks = [andrew, ann, charles, edward],
X = ann ;
...

但是在这种情况下,我们放宽了知识库中定义的答案顺序。

答案 1 :(得分:1)

您的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),则此操作将失败。这种方法不仅不正确,而且即使正确,也会非常“不稳定”。

我们可以利用setof/3 [swi-doc]谓词,该谓词不仅执行唯一性过滤器,而且还对元素进行排序。

由于我们要按降序对王室成员进行排序,因此,我们应该构造2元组(或封装两个参数的其他结构),其中第一个参数包含年龄,第二个参数表示对应的人。

然后我们可以使用member/2 [swi-doc]来“展开”单个统一的列表:

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. 

无论事实如何在源文件中排序。