谓词给出未绑定变量的列表,而不是所有可能的列表

时间:2018-10-09 15:06:42

标签: list prolog permutation

假设我有一个列表L1 = [1,2,3],我想写一个谓词,它可以找到该列表的所有排列,即

[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]

注意:我知道permutation(L1, L2).确实可以做到这一点,但是我想写一个自己的谓词来做练习。

我是一名序言新秀,所以我认为当两个列表L1和L2相互排列时,让我们先做一个谓词,返回true。要求是:

  1. 它们的长度必须相同
  2. L1中的每个元素都必须在L2中

所以我想到了这个:

permute(L1,L2):-
    forall(member(X,L1), member(X,L2)), % every element that is a member in L1 has to be a member in L2
    length(L1,A), % the length of the list L1 is A
    length(L2,A). % AND the length of the list L2 is A

因此,当我查询permute([1,2,3], [1,3,2]).时,确实得到了预期的true,并且permute([1,2,3], [1,3]).permute([1,2,3], [1,3,4]).都给出了false。因此,我的谓词可以查看2个列表是否彼此置换。

但是,如果我问:permute([1,2,3], A).,我希望能够看到所有有效的A,即[1,2,3]的所有排列。相反,我得到了无限的变量。 像A = [_942, _948, _954].

为什么会这样,为什么我不能浏览所有可能的列表A?有没有简单的方法可以修改我的代码以实现这一目标?

1 个答案:

答案 0 :(得分:2)

首先,您的两点定义是错误的。根据它,permute( [1,1,2], [1,2,2])应该保持(并且确实如此)。

“简单” 方法是使用select/3

select( [A|B], X):- select(A, X, Y), select(B, Y).
select( [], []).

它起作用,但仅在一个方向上起作用。即使添加(简单)same_length也无济于事:

permute( A, B):- same_length( A, B), select( B, A).

same_length( A, B):- length(A, N), length(B, N).   % wrong

% permute( [1,2,3], X).    % OK
% permute( X, [1,2,3]).    % doesn't terminate after the last solution

不,same_length/2的定义必须仔细,

same_length( [], []).
same_length( [_|A], [_|B]):- same_length(A, B).

然后 permute在两个方向都可以。