[英]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]]
我如何添加或減去SomeList
和SomeList2
來創建列表列表? 結果說了一筆
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)
在L1
和L2
每個元素上調用G
,從而得到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
為您處理。
除了@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.