如何在Prolog中将两个列表的所有元素相互相乘

时间:2015-05-19 13:32:34

标签: list prolog

我正在考虑如何将两个列表中的所有元素相互叠加。然后我想把所有结果都放在List3中。例如,

List1 = [1,3,5].
List2 = [2,6,7]. 

List3应包含[1x2,1x6,1x7,3x2,3x6,3x7,5x2,5x6,5x7]。 最后;

List3 = [2, 6, 7, 6, 18, 21, 10, 30, 35].

有可能吗?怎么做?我无法找到正确的方法。

5 个答案:

答案 0 :(得分:3)

以下是使用library(lambda)

的直接解决方案
product(Xs, Ys, Ps) :-
   maplist(Ys+\X^maplist({X,Ys}+\Y^YP^(YP=X*Y),Ys), Xs, PPs),
   append(PPs, Ps).

所以我们有Xs的外循环和Ys的内循环。

?- product([1,2,3],[4,5,6],Ps).
Ps = [1*4,1*5,1*6,2*4,2*5,2*6,3*4,3*5,3*6].

(YP=X*Y)替换为(YP is X*Y)(YP #= X*Y)。无论你喜欢什么。

答案 1 :(得分:3)

为什么不

prod(L1, L2, LP) :-
    bagof(P, X^Y^(member(X, L1), member(Y, L2), P is X * Y), LP).

答案 2 :(得分:2)

使用“交叉产品” - 此处显示 - 只是众多应用之一。继续这样:

:- meta_predicate xproduct(4,?,?,?).
xproduct(P_4,As) -->
   xproduct(P_4,As,As).

:- meta_predicate xproduct(4,?,?,?,?).
xproduct(P_4,As,Bs) -->
   xproduct_aux1(As,Bs,P_4).                % use 1st argument indexing for As

:- meta_predicate xproduct_aux1(?,?,4,?,?).
xproduct_aux1([]    ,_ , _ ) --> [].
xproduct_aux1([A|As],Bs,P_4) -->
   xproduct_aux2(Bs,[A|As],P_4).            % use 1st argument indexing for Bs

:- meta_predicate xproduct_aux2(?,?,4,?,?).
xproduct_aux2([],_,_) --> [].
xproduct_aux2([B|Bs],As,P_4) -->
   xproduct_(As,[B|Bs],P_4).

:- meta_predicate xproduct_(?,?,4,?,?).
xproduct_([],_,_) --> [].
xproduct_([A|As],Bs,P_4) -->
    xprod_(Bs,A,P_4),
    xproduct_(As,Bs,P_4).

:- meta_predicate xprod_(?,?,4,?,?).
xprod_([],_,_) --> [].
xprod_([B|Bs],A,P_4) -->
    call(P_4,A,B),
    xprod_(Bs,A,P_4).

让我们使用lambdas 运行您在问题中提供的查询:

:- use_module([library(clpfd),library(lambda)]).

?- phrase(xproduct(\X^Y^[Z|Zs]^Zs^(Z #= X*Y),[1,3,5],[2,6,7]),Fs).
Fs = [2,6,7,6,18,21,10,30,35].

以上lambda明确使用 ; 使用phrase//1,我们也可以隐式使用

?- phrase(xproduct(\X^Y^phrase(([Z],{Z #= X*Y})),[1,3,5],[2,6,7]),Fs).
Fs = [2,6,7,6,18,21,10,30,35].

使我们能够进行非常一般的查询。感谢@PauloMoura的建议!瞧!

?- phrase(xproduct(\X^Y^phrase(([Z],{Z #= X*Y})),As,Bs),
          [2,6,7,6,18,21,10,30,35]),
   maplist(labeling([]),[As,Bs]).
  As = [-2,-6,-7,-6,-18,-21,-10,-30,-35], Bs = [-1]
; As = [ 2, 6, 7, 6, 18, 21, 10, 30, 35], Bs = [ 1]
; As = [-1,-3,-5],                        Bs = [-2,-6,-7]
; As = [ 1, 3, 5],                        Bs = [ 2, 6, 7]
; As = [-1],                              Bs = [-2,-6,-7,-6,-18,-21,-10,-30,-35]
; As = [ 1],                              Bs = [ 2, 6, 7, 6, 18, 21, 10, 30, 35]
; false.

答案 3 :(得分:2)

一个简单的解决方案,不需要任何Prolog扩展(但当然,失去使用CLP(FD)的潜在好处)将是:

product(List1, List2, Product) :-
    % save a copy of the second list
    product(List1, List2, List2, Product).

product([], _, _, []).
product([X| Xs], List2, Rest2, Product) :-
    (   Rest2 == [] ->
        product(Xs, List2, List2, Product)
    ;   Rest2 = [Y| Ys],
        Z is X * Y,
        Product = [Z| Zs],
        product([X| Xs], List2, Ys, Zs)
    ).

这个解决方案是尾递归的,不会留下虚假的选择点。

答案 4 :(得分:1)

好的,首先看看这个问题executing operation for each list element in swi-prolog and others,了解如何for-eachlists进行操作。
其次,这是代码:

prod(X,[],[]).
prod(X,[HEAD|TAIL],L) :-  prod(X,TAIL,L1), W is X * HEAD, L = [W|L1].

prod2([],Y,[]).
prod2([HEAD|TAIL],Y,L) :- prod(HEAD,Y,L1), prod2(TAIL,Y,L2), append(L1,L2,L).

输出:

?- prod2([1,3,5] ,[2,6,7],G).
G = [2, 6, 7, 6, 18, 21, 10, 30, 35] .