在SWI-prolog中打印一对列表

时间:2017-01-01 11:06:52

标签: prolog

基本上,我想从一个列表中打印出这样的对

?- [1 2 3 4 5,R]

输出

R = [1, 2] 
R = [1, 3] 
R = [1, 4] 
R = [1, 5] 
R = [2, 3] 
R = [2, 4] 
R = [2, 5] 
R = [3, 4] 
R = [3, 5] 
R = [4, 5] 

我使用了创建子集并修改它的代码

sub(0,_,[]).
sub(N,[X|T],[X|R]):-N>0,N1 is N-1,sub(N1,T,R).
sub(N,[_|T],R):-N>0,sub(N,T,R).
我会打电话给你     子(2,[1,2,3,4,5],R)

但有没有办法在不使用计数器的情况下完成?

3 个答案:

答案 0 :(得分:2)

Prolog是关于定义关系(以规则的形式)并试图避免程序性思考(执行步骤以实现结果)。您可以通过将其分解为对的简单规则来解决此问题:

  1. 对于头部为H且尾部为T的列表,有效对为[H,E],其中ET的成员。
  2. 对于头部为H且尾部为T的列表,有效对是从T中选取的一对。
  3. 如果您考虑这些规则,它们是(1)互斥(没有与两个规则相匹配的解决方案),以及(2)它们是完整的(它们涵盖所有有效的解决方案)。

    在Prolog中写这些,你得到:

    pair([H|T], [H,E]) :- member(E, T).
    pair([_|T], P) :- pair(T, P).
    

    这提供了一种关系解决方案,产生:

    | ?- sub([a,b,c,d], S).
    
    S = [a,b] ? ;
    
    S = [a,c] ? ;
    
    S = [a,d] ? ;
    
    S = [b,c] ? ;
    
    S = [b,d] ? ;
    
    S = [c,d] ? ;
    
    (1 ms) no
    | ?-
    

    并且在更一般的情况下工作:

    | ?- pair(L, P).
    
    L = [A,B]
    P = [A,B] ? ;
    
    L = [A,B|_]
    P = [A,B] ? ;
    
    L = [A,_,B|_]
    P = [A,B] ? ;
    
    L = [A,_,_,B|_]
    P = [A,B] ? ;
    ...
    

答案 1 :(得分:1)

一种简单的方法:

?- L = [1,2,3,4,5], forall((nth1(I,L,X), nth1(J,L,Y), I<J), writeln(I/J)).
1/2
1/3
1/4
1/5
2/3
2/4
2/5
3/4
3/5
4/5
L = [1, 2, 3, 4, 5].

答案 2 :(得分:0)

是的,因为您不必考虑任意长度的子集。

您需要考虑两个步骤,两者都有两种变体。

  1. 选择对中的第一个元素:
    1. 使用列表的头部
    2. 丢弃头部并从列表尾部挑出
  2. 选择对中的第二个元素:
    1. 使用列表的头部
    2. 丢弃头部并从列表尾部挑出
  3. % Use the head as the first element
    pairs((H, P2), [H | T]) :- pairs((H, P2), T).
    
    % If we have the first element, use the head as the second element
    pairs((P1, H), [H | _]) :- nonvar(P1).
    
    % Ignore the head and pick what we need out of the tail
    pairs(P, [_ | T]) :- pairs(P, T).