列表的对数事实和接受列表排列的递归谓词



我有接受某些列表的事实。这些列表已排序。

acceptedList([1,2,3]).
acceptedList([4,5,6]).
acceptedList([7,8,9]).

现在,我也想接受接受名单的任何排列。为此,我想对输入列表进行排序并将其与上述事实进行匹配。

我可以使用名称不acceptedList的谓词来解决这个问题,但我想知道这是否可以以递归方式完成。

这是我的想法:

acceptedList(List) :-
    sort(List,SortedList),    % Sort the list to match against the facts.
    acceptedList(SortedList). % Match against the facts.

我的想法是这个谓词应该接受输入列表,例如 [3,2,1] .然而,这似乎是一个无限循环,而且由于我乏善可陈的序言知识,我需要一些帮助来理解为什么以及是否可以使用acceptedList事实和名称相同的谓词来解决这个问题。

Prolog有一个带有谓词permutation/2的库lists,可以为给定列表生成所有排列。

所以温可以写:

acceptedList(Lb) :-
    acceptedList(La),
    permutation(La,Lb).

但是现在我们有一个问题:这个谓词会不断生成列表。由于在它列举了事实之后,它将触发上面定义的谓词,这将再次枚举排列,因此我们将产生排列的排列,排列的排列的排列,等等。这可能不是我们想要的。

对此的解决方案是将事实与谓词分开。因此,我们可以将acceptedList/1重写为acceptedListFact/1

acceptedListFact([1,2,3]).
acceptedListFact([4,5,6]).
acceptedListFact([7,8,9]).
acceptedList(Lb) :-
    acceptedListFact(La),
    permutation(La,Lb).

因此,我们将La与一个被陈述为事实的清单统一起来。

现在我们得到以下acceptedList/2

?- acceptedList(L).
L = [1, 2, 3] ;
L = [1, 3, 2] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [3, 1, 2] ;
L = [3, 2, 1] ;
L = [4, 5, 6] ;
L = [4, 6, 5] ;
L = [5, 4, 6] ;
L = [5, 6, 4] ;
L = [6, 4, 5] ;
L = [6, 5, 4] ;
L = [7, 8, 9] ;
L = [7, 9, 8] ;
L = [8, 7, 9] ;
L = [8, 9, 7] ;
L = [9, 7, 8] ;
L = [9, 8, 7] ;
false.

最新更新