在Prolog

时间:2016-10-10 10:47:28

标签: algorithm prolog

我学习Prolog大约一个星期,所以我是一个新手。 我试图做一个附加列表元素的函数。

所以输入将是:[ [[a,b,c],[g,h,i]], [[j,k,l],[m,n,o]], [[s,t,u],[v,w,x]] ].

输出结果为:[ [a,b,c,j,k,l,s,t,u], [g,h,i,m,n,o,v,w,x] ].

或者

输入:[ [[a,b], [c,d]], [[e,f], [g,h]], [[i,j],[k,l]] ].

输出:[ [a,b,e,f,i,j], [c,d,g,h,k,l] ].

重要的是,它必须与许多元素一起工作,而不仅仅是3。 我写了这个,但它只适用于2个元素,所以我只能用它来做。

merge([],[],[]).
merge(L1,[],L1).
merge([H1|T1],[H2|T2],LL):-
   append(H1, H2, HE),
   merge(T1,T2,TE),
   append([HE], TE, LL).

1 个答案:

答案 0 :(得分:1)

如果我理解你的问题......

首先,如果您知道您的输入中只有两个嵌套级别,并且如果您的Prolog具有用于映射和折叠的高阶谓词,并且如果您可以编写它们,则可以简单地写:

merge_foldl([], []).
merge_foldl([X|Xs], R) :-
    reverse([X|Xs], [Y|Ys]),
    foldl(maplist(append), Ys, Y, R).

这与SWI-Prolog的预期一致。 这是你的两个例子:

?- merge_foldl([ [[a,b,c],[g,h,i]], [[j,k,l],[m,n,o]], [[s,t,u],[v,w,x]] ], R).
R = [[a, b, c, j, k, l, s, t, u], [g, h, i, m, n, o, v, w, x]].

?- merge_foldl([ [[a,b], [c,d], [e,f]], [[g,h], [i,j], [k,l]] ], R).
R = [[a, b, g, h], [c, d, i, j], [e, f, k, l]].

如果您无法访问foldrfoldl,则必须对折叠进行硬编码:

merge([], []).
merge([X|Xs], Result) :-
    merge_maplist(Xs, X, Result).

merge_maplist([], Result, Result).

这不是全部,但它表示,如果您位于列表列表的末尾,则最后一个元素就是结果。

现在,您必须定义附加到每个子列表前面的步骤。使用maplist

可以更轻松
merge_maplist([X|Xs], Prev, Result) :-
    merge_maplist(Xs, X, Result0),
    maplist(append, Prev, Result0, Result).

请注意,我们在这里"仿效"通过使用非尾递归定义进行右折叠:在递归步骤之后,我们正在反向执行追加。对于尾递归定义(与硬编码左折叠相同),您必须首先反转原始列表!

所以你继续从输入中删除一个列表列表,直到完成为止。然后,使用maplistappend/3应用于前一个元素的每对列表和到目前为止的结果,以获得最终结果。

如果您无法访问maplist,您也必须对映射进行硬编码。对于append/3采用的三个参数:

map_append([], [], []).
map_append([X|Xs], [Y|Ys], [Z|Zs]) :-
    append(X, Y, Z),
    map_append(Xs, Ys, Zs).

,您的merge/2merge_/3成为:

merge([], []).
merge([X|Xs], Result) :-
    merge_(Xs, X, Result).

merge_([], Result, Result).
merge_([X|Xs], Prev, Result) :-
    merge_(Xs, X, Result0),
    map_append(Prev, Result0, Result).

如果您有更高阶的谓词,这是很多可以很好解决的代码。

相关问题