2015-05-19 217 views
2

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

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

List3应包含[1×2,1X6,1X7,3×2,3×6,3X7,5×2,5×6,5×7]。 最后;

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

有没有可能这样做?怎么做?我找不到一个正确的方法。

+4

嗯,这是一个图灵完备的语言,因此它必须能够 –

+1

首先,你怎么可以乘以一个数一个列表中的所有元素?接下来,你如何使用前面的代码来解决你的问题? – joel76

回答

1

好,首先对这个问题executing operation for each list element in swi-prolog and others一看就知道该怎么做listsfor-each操作。
其次,这里是代码:

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] . 
+0

感谢您的帮助 – Leonard

+2

此解决方案不是尾递归的,需要对append/3进行相对昂贵的调用,不会利用大多数Prolog系统上的第一个参数索引,并留下虚假的选择点。 –

+0

@PauloMoura:你说得对,但大多数初学者更喜欢简单易读的代码,而不是复杂的代码。 – houssam

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. 
+1

感谢您花费时间解决我的问题和解决方案 – Leonard

+3

添加一个查询示例将有助于强调使用CLP(FD)的优点,与仅使用标准,基本算术的简单解决方案相比较。 –

+0

@PauloMoura。谢谢你的建议! – repeat

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) 
    ). 

该解决方案是尾递归的并且不会留下虚假的选择点。

+2

人们帮助需要帮助的人,它会创造一个更美好的世界。感谢您的关注 – Leonard

3

下面是使用library(lambda)

product(Xs, Ys, Ps) :- 
    maplist(Ys+\X^maplist({X,Ys}+\Y^YP^(YP=X*Y),Ys), Xs, PPs), 
    append(PPs, Ps). 

所以我们有一个外环的XsYs内环相当直接的解决方案。

?- 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 is X*Y)(YP #= X*Y)更换(YP=X*Y)。无论你喜欢什么。

3

为什么不

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

“为什么不”:因为它没有扩展到约束条件(在许多实现中)。 – false

+0

好吧,我只有SWI-Prolog! – joel76

+1

在SWI中,当用'#='替换'is'时。你用'prod([X],[Y],Zs)'定义'正确成功了'Zs = [_G1],X * Y#= _G1',但是对于'prod([X,X],[Y ],ZS)'。这些微妙的错误使调试成为一场噩梦。 – false

相关问题