Prolog - 在给定列表中写入k个数字的组合

时间:2012-04-30 17:44:50

标签: prolog combinations

我试图在prolog中定义一个函数,它接受形式组合的参数(3,[a,b,c,d],L),结果返回

L=a,b,c
L=a,b,d
L=a,c,d
L=b,c,d

我的实施如下:

combination(K,argList,L):-
unknown(X,argList,Y),
Z is select(X,argList),
length(Z,K),
L is Z,
combination(K,Z,L).

unknown(X,[X|L],L).
unknown(X,[_|L],R) :- unknown(X,L,R).

未知谓词的行为如下: ![在此输入图像说明] [1]

请帮忙。

2 个答案:

答案 0 :(得分:0)

使用您对unknown/3的定义时想到的最简单的解决方案是:

combination(0, _, []) :- 
    !.
combination(N, L, [V|R]) :-
    N > 0,
    NN is N - 1,
    unknown(V, L, Rem),
    combination(NN, Rem, R).

unknown(X,[X|L],L).
unknown(X,[_|L],R) :- 
    unknown(X,L,R).

说明:combination/3的第二个子句试图从列表L中选择一个元素,谓词unknown/3以线性方式执行,返回余数{{1} }。一旦从列表Rem中选择的元素数超过L,就会触发基本情况(N的第一个子句),终止分支。请注意,combination/3的定义依赖于combination/3的非确定性特性,它为选择备用列表元素留下了选择点。

答案 1 :(得分:0)

出于某种原因,我接受了一个挑战,提出了一个组合/ 3谓词,这没有留下最后的选择点。如果不使用sharky解决方案进行修改,我们就会得到以下行为:

?- combination(2,[a,b,c],X).
X = [a, b] ;
X = [a, c] ;
X = [b, c] ;
No

此要求有点符合Gertjan van Noord member / 2技巧的精神。但是我们宁愿通过计算给定列表的长度来解决这个问题:

:- use_module(library(basic/lists)).

% combination(+Integer, +List, -List)
combination(0, _, []) :-  !.
combination(N, L, [A|R]) :-
    M is N-1,
    length(L, K),
    J is K-N,
    unknown(J, A, L, H),
    combination(M, H, R).

% unknown(+Integer, -Elem, +List, -List)
unknown(0, X, [X|L], L) :- !.
unknown(_, X, [X|L], L).
unknown(N, X, [_|L], R) :-
    M is N-1,
    unknown(M, X, L, R).

上述谓词仍然不是最优的,我们只能计算一次长度。但是它显示了我们删除了多余的选择点的位置。现在,谓词运行如下:

Jekejeke Prolog 4, Runtime Library 1.4.1 (August 20, 2019)
(c) 1985-2019, XLOG Technologies GmbH, Switzerland

?- combination(2,[a,b,c],X).
X = [a, b] ;
X = [a, c] ;
X = [b, c]