列表元素的置换组合 - Prolog

Sim*_*mon 10 prolog

如何生成列表元素的所有可能组合?

例如,给定列表[1,2,3],我想设计一个谓词,其形式comb([1,2,3], L).应返回以下答案L:

[1]  
[2]  
[3]  
[1,2]  
[2,1]  
[1,3]  
[3,1]  
[2,3] 
[3,2]  
[1,2,3]  
[1,3,2]  
[2,1,3]  
[2,3,1]  
[3,1,2]  
[3,2,1] 
Run Code Online (Sandbox Code Playgroud)

har*_*ath 11

您要求的是涉及列表的组合(选择子集)和排列(重新排列顺序).

您的示例输出意味着空列表不被视为有效解决方案,因此我们将在后面的实现中将其排除.如果这是一个疏忽,重新考虑.此实现也以与示例输出不同的顺序生成解决方案.

comb(InList,Out) :-
    splitSet(InList,_,SubList),
    SubList = [_|_],     /* disallow empty list */
    permute(SubList,Out).

splitSet([ ],[ ],[ ]).
splitSet([H|T],[H|L],R) :-
    splitSet(T,L,R).
splitSet([H|T],L,[H|R]) :-
    splitSet(T,L,R).

permute([ ],[ ]) :- !.
permute(L,[X|R]) :-
    omit(X,L,M),
    permute(M,R).

omit(H,[H|T],T).
omit(X,[H|L],[H|R]) :-
    omit(X,L,R).
Run Code Online (Sandbox Code Playgroud)

与Amzi一起测试!序言:

?- comb([1,2,3],L).

L = [3] ;

L = [2] ;

L = [2, 3] ;

L = [3, 2] ;

L = [1] ;

L = [1, 3] ;

L = [3, 1] ;

L = [1, 2] ;

L = [2, 1] ;

L = [1, 2, 3] ;

L = [1, 3, 2] ;

L = [2, 1, 3] ;

L = [2, 3, 1] ;

L = [3, 1, 2] ;

L = [3, 2, 1] ;
no
Run Code Online (Sandbox Code Playgroud)

  • 红色用法:`置换(Xs,Ys),Xs = [_]` (3认同)
  • 你是对的,但你的答案仍然包含这个有问题的代码. (3认同)

rep*_*eat 5

保持纯洁的定义comb/2基础上same_length/2prefix/2foldl/4select/3

梳(As,Bs):-
   same_length(As,Full),
   Bs = [_ | _],
   前缀(Bs,Full),
   foldl(select,Bs,As,_)。

这是OP给出的示例查询:

?- comb([1,2,3],Xs).
  Xs = [1]
; Xs = [2]
; Xs = [3]
; Xs = [1,2]
; Xs = [1,3]
; Xs = [2,1]
; Xs = [2,3]
; Xs = [3,1]
; Xs = [3,2]
; Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
Run Code Online (Sandbox Code Playgroud)

好!但是,如果作为第一个参数给出的列表包含重复项怎么办?

?- comb([1,1,2],Xs).
  Xs = [1]
; Xs = [1]                   % (redundant)
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [1,1]                 % (redundant)
; Xs = [1,2]                 % (redundant)
; Xs = [2,1]
; Xs = [2,1]                 % (redundant)
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [1,1,2]               % (redundant)
; Xs = [1,2,1]               % (redundant)
; Xs = [2,1,1]
; Xs = [2,1,1]               % (redundant)
; false.
Run Code Online (Sandbox Code Playgroud)

不完全的!我们可以摆脱以上多余的答案吗?是的,只需使用selectd/3

梳(As,Bs):-
   same_length(As,Full),
   Bs = [_ | _],
   前缀(Bs,Full),
   foldl(selected,Bs,As,_)。

因此,让我们通过改进的实现再次在查询之上运行comb/2

?- comb([1,1,2],Xs).
  Xs = [1]
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [2,1]
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [2,1,1]
; false.
Run Code Online (Sandbox Code Playgroud)

  • 很棒的解决方案,+ 1!我希望我们很快会看到一个包含所有这些纯基本谓词的库!`library(purple)`:* Pure Prolog Library(Elementary)*? (4认同)