如何在 Prolog 中将两个列表的所有元素相互相乘
How to multiply all elements of two lists with each other in 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].
可以吗?怎么做?我找不到正确的方法。
使用 dcg! "Cross product"——此处显示——只是众多应用程序中的一个。像这样进行:
:- 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).
让我们用clpfd and 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 表达式使用 difference-lists 显式 ;
使用 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].
clpfd 使我们能够进行非常一般的查询。感谢@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.
嗯,先看一下这个问题executing operation for each list element in swi-prolog and others,了解如何对lists
进行for-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] .
不需要任何 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)
).
这个解决方案是尾递归的,不会留下虚假的选择点。
这是一个相当直接的解决方案,使用 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)
。随心所欲。
为什么不
prod(L1, L2, LP) :-
bagof(P, X^Y^(member(X, L1), member(Y, L2), P is X * Y), LP).
我在考虑如何将两个列表的所有元素相互相乘。然后我想把所有的结果都放在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].
可以吗?怎么做?我找不到正确的方法。
使用 dcg! "Cross product"——此处显示——只是众多应用程序中的一个。像这样进行:
:- 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).
让我们用clpfd and 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 表达式使用 difference-lists 显式 ;
使用 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].
clpfd 使我们能够进行非常一般的查询。感谢@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.
嗯,先看一下这个问题executing operation for each list element in swi-prolog and others,了解如何对lists
进行for-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] .
不需要任何 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)
).
这个解决方案是尾递归的,不会留下虚假的选择点。
这是一个相当直接的解决方案,使用 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)
。随心所欲。
为什么不
prod(L1, L2, LP) :-
bagof(P, X^Y^(member(X, L1), member(Y, L2), P is X * Y), LP).