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

时间:2016-07-07 18:30:39

标签: list 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]]) 

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

2 个答案:

答案 0 :(得分:3)

最简单的方法是使用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)GL1的每个元素上调用L2,从而生成R的每个元素。由于L1L2的每个元素都是一个列表,因此G在这种情况下为maplist(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为您处理。

答案 1 :(得分:3)

除了@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 = -