繁体   English   中英

在prolog中减去或添加列表列表?

[英]Subtracting or adding lists of lists in prolog?

我对prolog很新,我试图搞清楚列表清单。 我很好奇如何添加两个列表列表或减去它们导致一个列表列表。 如果我有两个列表列表可以说,

SomeList = [[1,2,3,4],[5,6,7,8]]  
SomeList2 = [[1,2,3,4],[5,6,7,8]]

我如何添加或减去SomeListSomeList2来创建列表列表? 结果说了一笔

sumList([[2,4,6,8],[10,12,14,16]]) 

反之亦然? 任何帮助将不胜感激,不是寻找代码,而是为了洞察力!

最简单的方法是使用maplist

add(X, Y, Z) :- Z is X + Y.

op_lists(L1, L2, R) :-
    maplist(maplist(add), L1, L2, R).

这使:

| ?- op_lists([[1,2,3,4],[5,6,7,8]], [[1,2,3,4],[5,6,7,8]], R).

R = [[2,4,6,8],[10,12,14,16]]

yes
| ?-

在表达式中:

maplist(maplist(add), L1, L2, R).

maplist(G, L1, L2, R)L1L2每个元素上调用G ,从而得到R每个元素。 由于L1L2每个元素都是一个列表,因此在这种情况下Gmaplist(add) ,它在子列表的每个元素上调用add

显然,您可以将add(X, Y, Z)修改为您希望在每对元素上执行的任何操作。 您还可以使用CLP(FD)使添加更“关系”:

add(X, Y, Z) :- Z #= X + Y.

然后你也会得到,例如:

| ?- op_lists([[1,2,3,4],[5,6,7,8]], L, [[3,6,9,12],[10,12,14,16]]).

L = [[2,4,6,8],[5,6,7,8]]

yes
| ?-

如果你想在没有maplist情况下这样做,你仍然可以使用add/3并使用两层方法:

op_lists([], [], []).
op_lists([LX|LXs], [LY|LYs], [LR|LRs]) :-
    op_elements(LX, LY, LR),
    op_lists(LXs, LYs, LRs).

op_elements([], [], []).
op_elements([X|Xs], [Y|Ys], [R|Rs]) :-
    add(X, Y, R),
    op_elements(Xs, Ys, Rs).

您可以在此处查看简单列表处理模式,使用maplist为您处理。

除了@lurker(+1)提供的解决方案之外,我还会添加使用DCG的可能性,因为您正在处理列表。 对于可用的操作,我建议定义一个稍微更一般的谓词opfd / 4而不是add / 3。 以下是您问题中提到的加法和减法的示例性规则,您可以使用这些作为模板来添加其他两位算术运算:

opfd(+,X,Y,Z) :-
   Z #= X+Y.
opfd(-,X,Y,Z) :-
   Z #= X-Y.

由于所需的操作是一个参数,您只需要一个DCG规则来覆盖所有操作(在相应的目标上标记为(1))。 当然,这样一来,您必须在关系中指定所需的操作作为参数,并将其传递给DCG。 这些DCG的结构与@lurker提出的最后一个解决方案非常相似,不同之处在于结果列表不作为参数出现,因为这是DCG描述的内容。 为了便于比较,我将坚持使用名称op_lists // 3和op_elements // 3,调用谓词应该被称为lists_op_results / 4:

lists_op_results(L1,L2,Op,Rs) :-
   phrase(op_lists(Op,L1,L2),Rs).

op_lists(_Op,[],[]) -->
   [].
op_lists(Op,[X|Xs],[Y|Ys]) -->
   {phrase(op_elements(Op,X,Y),Rs)},
   [Rs],
   op_lists(Op,Xs,Ys).

op_elements(_Op,[],[]) -->
   [].
op_elements(Op,[X|Xs],[Y|Ys]) -->
   {opfd(Op,X,Y,R)},                    % <-(1)
   [R],
   op_elements(Op,Xs,Ys).

示例查询:

   ?- lists_op_results([[1,2,3,4],[5,6,7,8]], [[1,2,3,4],[5,6,7,8]], +, R).
R = [[2,4,6,8],[10,12,14,16]]
   ?- lists_op_results([[1,2,3,4],[5,6,7,8]], [[1,2,3,4],[5,6,7,8]], -, R).
R = [[0,0,0,0],[0,0,0,0]]

@ lurker的例子:

   ?- lists_op_results([[1,2,3,4],[5,6,7,8]], L, +, [[3,6,9,12],[10,12,14,16]]).
L = [[2,4,6,8],[5,6,7,8]]

您还可以询问是否存在适合给定列表的操作:

   ?- lists_op_results([[1,2,3,4],[5,6,7,8]], L, Op, [[3,6,9,12],[10,12,14,16]]).
L = [[2,4,6,8],[5,6,7,8]],
Op = + ? ;
L = [[-2,-4,-6,-8],[-5,-6,-7,-8]],
Op = -

旁注:由于操作是opfd / 4的第一个参数,你也可以像@ lurker的第一个解决方案中的建议一样使用maplist。 你必须传递它缺少最后三个参数:

   ?- maplist(maplist(opfd(Op)),[[1,2,3,4],[5,6,7,8]], L, [[3,6,9,12],[10,12,14,16]]).
L = [[2,4,6,8],[5,6,7,8]],
Op = + ? ;
L = [[-2,-4,-6,-8],[-5,-6,-7,-8]],
Op = -

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM