我对prolog很新,我试图搞清楚列表清单。我很好奇如何添加两个列表列表或减去它们导致一个列表列表。如果我有两个列表列表,可以说,
SomeList = [[1,2,3,4],[5,6,7,8]]
SomeList2 = [[1,2,3,4],[5,6,7,8]]
如何添加或减去SomeList
和SomeList2
来创建列表列表?导致一笔费用
sumList([[2,4,6,8],[10,12,14,16]])
反之亦然?任何帮助将不胜感激,不是寻找代码,而是为了洞察力!
答案 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)
在G
和L1
的每个元素上调用L2
,从而生成R
的每个元素。由于L1
和L2
的每个元素都是一个列表,因此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 = -