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

时间:2017-11-13 08:58:01

标签: list prolog permutation

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

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]。 然而,这似乎进入了一个无限循环,并且由于我乏味的prolog知识,我需要一些帮助来理解为什么以及是否可以使用acceptedList事实和名称相同的谓词来解决这个问题。

1 个答案:

答案 0 :(得分:3)

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

所以你可以写:

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 s:

?- 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.