Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 在Prolog中如何将两个列表的所有元素相乘_List_Prolog_Dcg_Clpfd_Difference Lists - Fatal编程技术网

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

List 在Prolog中如何将两个列表的所有元素相乘,list,prolog,dcg,clpfd,difference-lists,List,Prolog,Dcg,Clpfd,Difference Lists,我在考虑如何将两个列表中的所有元素相乘。然后我想把所有结果放在列表3中。比如说, 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]. 有可能吗?怎么做?我找不到正确的方法。使用“交叉产品”-此处显示的只是众多应用程序中的一个。这样做: :- meta_predicate xproduct(4

我在考虑如何将两个列表中的所有元素相乘。然后我想把所有结果放在
列表3
中。比如说,

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].
有可能吗?怎么做?我找不到正确的方法。

使用“交叉产品”-此处显示的只是众多应用程序中的一个。这样做:

:- 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).
让我们使用和 运行您在问题中提供的查询:

:- 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]. 使我们能够进行非常一般的查询。感谢@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.

好的,首先看看这个问题,了解如何对
列表上的每个
操作执行

其次,代码如下:

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

一个不需要任何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)
    ).

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

这里是一个使用
库(lambda)

因此,我们有一个用于
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为X*Y)
(YP#=X*Y)
。你喜欢什么都行。

为什么不呢

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

这是一种图灵完全语言,所以它必须是可能的。首先,你怎么能把一个列表的所有元素乘以一个数字呢?接下来,您如何使用前面的代码来解决您的问题?感谢您花时间回答我的问题和解决方案。添加一个查询示例将有助于突出使用CLP(FD)与仅使用标准、基本、算术的简单解决方案相比的优势。@PauloMoura。谢谢你的建议!此解决方案不是尾部递归,需要相对昂贵的
append/3
调用,没有利用大多数Prolog系统上的第一个参数索引,并且留下了虚假的选择点。@PauloMoura:你是对的,但大多数初学者更喜欢简单可读的代码而不是复杂的代码。嗯,这是一个“正确的”但正如@PauloMoura所指出的,它有很多不足之处。我甚至不会讨论编码准则(如果您使用Prolog编程,请看一看)。但是,既然OP可能对学习Prolog不太感兴趣,我想把你的解决方案当作“正确的”不会有太大的伤害。帮助需要帮助的人,会创造一个更美好的世界。感谢大家关注“为什么不”:因为它不会扩展到约束(在许多实现中)。好的,我只使用SWI Prolog!在SWI中,将
替换为
#=
时。您对
prod([X],[Y],Zs)
的定义在
Zs=[u G1],X*Y=[u G1
中正确成功,但在
prod([X,X],[Y],Zs)
中错误失败。这些微妙的错误使调试成为一场噩梦。一个可能更令人信服的例子:
prod([1,1],[2],Zs)
正确地成功地使用
Zs=[2,2]
。但是,
prod([1,1],[Y],Zs),Y=2,虽然在逻辑上是等价的,但现在失败了,因为第一个目标失败了。当我发布代码时,我必须说我没有想到所有这些问题!我经常忘记,在Prolog中,参数可以在谓词调用之前统一,也可以不统一。
?- 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].
prod(L1, L2, LP) :-
    bagof(P, X^Y^(member(X, L1), member(Y, L2), P is X * Y), LP).