计算给定元素列表中包含任意n个元素的所有可能组合的列表

时间:2018-11-09 11:27:57

标签: prolog

我在如何用Prolog编写程序中遇到一个问题,该程序需要一个元素列表和一个大小并返回给定大小的元素的所有可能组合的列表。

这里是一个具体的例子来阐明问题:

?- comb([a, b, c, d, e], 3, L).
L = [a,b,c] ;
L = [a,b,d] ;
L = [a,b,e] ;
... 

由于我是Prolog的新手,所以我想获得一些解决此问题的提示。

我打算修复一个元素,然后将递归应用于其余职位。但是我缺乏如何实现这一点的想法。

提前感谢您的建议:)!

1 个答案:

答案 0 :(得分:1)

最直接的方法是在Prolog中使用典型的递归模式。

有一个简单的基本情况,其中长度为0:

comb(_, 0, []).

这种情况下,如果我的长度为0,则子列表为空列表。无论完整列表如何,都是如此,因此我们使用_,因为我们不在乎它是什么。

递归地,您可以通过两种可能的方式使第3个参数成为第一个参数的长度N的子列表:

  1. 如果我有一个列表[X|Xs](第一个元素是X,列表的其余部分是Xs)且长度为N,则一个条件是N > 0,因为已经处理了0情况。另外,子列表S看起来像[X|T],其中TXs的子列表,并且长度为N1,其中N1小于1 N

  2. 如果我有一个列表[X|Xs](第一个元素是X,列表的其余部分是Xs)和一个长度N,那么我将拥有在这种情况下,条件N > 0也是如此,子列表S将是长度为Xs的{​​{1}}子列表。由于在这种情况下我不关心N,因此可以将其写为X

用语言描述您的谓词需要做什么,并建议两个谓词从句。在这里,我采用的方法与我在使用_谓词对您的问题的评论中提出建议时最初考虑的方法不同。在上面,您不需要使用该谓词。

额外信用

如果使用CLP(FD),这是Prolog进行整数推理的方式,则可以使用上述方法轻松获得更通用的解决方案。在CLP(FD)中,您将使用length/2代替N #> 0,并使用N > 0代替N1 #= N - 1。使用这种方法,您可以获得如下结果:

N1 is N - 1

或者这个...

| ?- length(List, 3), comb(List, N, Sublist).

List = [_,_,_]
N = 0
Sublist = [] ? a

List = [A,_,_]
N = 1
Sublist = [A]

List = [A,B,_]
N = 2
Sublist = [A,B]

List = [A,B,C]
N = 3
Sublist = [A,B,C]

List = [A,_,B]
N = 2
Sublist = [A,B]

List = [_,A,_]
N = 1
Sublist = [A]

List = [_,A,B]
N = 2
Sublist = [A,B]

List = [_,_,A]
N = 1
Sublist = [A]

no
| ?-