简体   繁体   English

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

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

I am fairly new to prolog and am trying to mess around with lists of lists. 我对prolog很新,我试图搞清楚列表清单。 I am curious on how to add two lists of lists or subtract them resulting in one list of list. 我很好奇如何添加两个列表列表或减去它们导致一个列表列表。 If I have two lists of lists lets say, 如果我有两个列表列表可以说,

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

How could I add or subtract SomeList and SomeList2 to create a list of lists? 我如何添加或减去SomeListSomeList2来创建列表列表? Resulting in a sum of say 结果说了一笔

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

or vice-versa for subtraction? 反之亦然? Any help would be appreciated not looking for code but for insight ! 任何帮助将不胜感激,不是寻找代码,而是为了洞察力!

The easiest approach is with maplist : 最简单的方法是使用maplist

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

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

Which gives: 这使:

| ?- 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
| ?-

In the expression: 在表达式中:

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

maplist(G, L1, L2, R) calls G on each element of L1 and L2 , resulting in each element of R . maplist(G, L1, L2, R)L1L2每个元素上调用G ,从而得到R每个元素。 Since each element of L1 and L2 is a list, then G in this case is maplist(add) which calls add on each element of the sublists. 由于L1L2每个元素都是一个列表,因此在这种情况下Gmaplist(add) ,它在子列表的每个元素上调用add

You can obviously modify add(X, Y, Z) to be whatever operation you wish on each pair of elements. 显然,您可以将add(X, Y, Z)修改为您希望在每对元素上执行的任何操作。 You can also make the addition more "relational" by using CLP(FD): 您还可以使用CLP(FD)使添加更“关系”:

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

Then you also get, for example: 然后你也会得到,例如:

| ?- 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
| ?-

If you wanted to do this without maplist , you could still use add/3 and use a two-layer approach: 如果你想在没有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).

You can see the simple list processing pattern here, which the use of maplist takes care of for you. 您可以在此处查看简单列表处理模式,使用maplist为您处理。

Besides the solutions presented by @lurker (+1), I would also add the possibility to use DCGs, since you are working on lists. 除了@lurker(+1)提供的解决方案之外,我还会添加使用DCG的可能性,因为您正在处理列表。 For the available operations I suggest to define a slightly more general predicate opfd/4 instead of add/3. 对于可用的操作,我建议定义一个稍微更一般的谓词opfd / 4而不是add / 3。 Here are exemplary rules for addition and subtraction as asked in your question, you can use these as templates to add other two-place arithmetic operations: 以下是您问题中提到的加法和减法的示例性规则,您可以使用这些作为模板来添加其他两位算术运算:

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

As the desired operation is an argument, you only need one DCG-rule to cover all operations (marked as (1) at the corresponding goal). 由于所需的操作是一个参数,您只需要一个DCG规则来覆盖所有操作(在相应的目标上标记为(1))。 This way, of course, you have to specify the desired operation as an argument in your relation and pass it on to the DCGs. 当然,这样一来,您必须在关系中指定所需的操作作为参数,并将其传递给DCG。 The structure of these DCGs is very similar to the last solution presented by @lurker, except that the resulting list does not appear as an argument since that is what the DCGs describe. 这些DCG的结构与@lurker提出的最后一个解决方案非常相似,不同之处在于结果列表不作为参数出现,因为这是DCG描述的内容。 For easier comparison I will stick with the names op_lists//3 and op_elements//3, the calling predicate shall be called lists_op_results/4: 为了便于比较,我将坚持使用名称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).

Example queries: 示例查询:

   ?- 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's example: @ 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]]

You can also ask if there is an operation that fits the given lists: 您还可以询问是否存在适合给定列表的操作:

   ?- 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 = -

On a sidenote: Since the operation is the first argument of opfd/4 you can also use it with maplist as suggested in @lurker's first solution. 旁注:由于操作是opfd / 4的第一个参数,你也可以像@ lurker的第一个解决方案中的建议一样使用maplist。 You just have to pass it lacking the last three arguments: 你必须传递它缺少最后三个参数:

   ?- 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