Prolog将元素转换为列表

时间:2017-05-09 13:00:32

标签: prolog

我需要谈谈我的任务和解决方案:

定义一个语句来反转两个参数,一个列表和另一个第二个列表,其元素的顺序相反。我们不能使用反向内置。

Example:

> invierte( [a, [b, c], d, [e, f]], L)

L = [[e, f], d, [b, c], a]

我的建议:

invierte([],[]).
invierte([X],[X]).
invierte([H|T], Result) :-
invierte([T|H]), Result).

我怀疑是否需要在一般情况下将输入第一个列表分为:

invierte([H|T], Result) :-
invierte([T|H]), Result).

invierte([H,Y|T], Result) :-
invierte([Y,H|T]), Result).

感谢您的提示!

4 个答案:

答案 0 :(得分:3)

您可以使用foldl和差异列表:

:-use_module(library(lambda)).

inverse(In, Out) :-
    foldl(\X^Y^Z^append_dl([X|U]-U, Y, Z), In, V-V, Out-[]).

append_dl(A-B, B-C, A-C).

例如

 ?- inverse([1,2,3], X).
X = [3,2,1].

修改 在User9213的第二个版本之后我们可以写

:-use_module(library(lambda)).

inverse(In, Out) :-
    foldl(\X^Y^Z^Z=[X|Y], In, [], Out).

答案 1 :(得分:3)

如果你想做更多花哨而不是太花哨,你可以像这样使用foldl:

list_rev_foldl([], []).
list_rev_foldl([X|Xs], R) :-
    foldl(rev, Xs, [X], R).

rev(X, Ys, [X|Ys]).

答案 2 :(得分:3)

在描述列表时,DCG通常会产生易于阅读的代码。另外,让我们选择一个更具声明性的名称,它反映了谓词的关系性质,比如list_invlist / 2。然后你描述一个反转列表的样子:

list_invlist(L,I) :-      % the inverse of the list L
   phrase(invseq(L),I).   % is described by invseq//1

invseq([]) -->            % the inverse of the empty list
   [].                    % is the empty list
invseq([X|Xs]) -->        % the inverse of the list [X|Xs] is
   invseq(Xs),            % the inverse of the list Xs
   [X].                   % followed by X

您帖子中的示例查询:

   ?- list_invlist([a,[b,c],d,[e,f]],I).
I = [[e,f],d,[b,c],a]

请注意,谓词也可以在其他方向上使用,就像它的关系名称所暗示的那样。但是,在产生第一个解决方案list_invlist / 2循环之后。

   ?- list_invlist(L,[[e,f],d,[b,c],a]).
L = [a,[b,c],d,[e,f]] ? ;
...                                        % <- loop

这是由于invseq // 2的递归规则中的左递归。您可以通过在list_invlist / 2中添加约束来限制两个列表的长度(DCG规则保持不变)来解决这个问题:

list_invlist(L,I) :-
   samelength(L,I),
   phrase(invseq(L),I).

samelength([],[]).
samelength([X|Xs],[Y|Ys]) :-
   samelength(Xs,Ys).

现在,谓词终止于第二个查询:

   ?- list_invlist(L,[[e,f],d,[b,c],a]).
L = [a,[b,c],d,[e,f]]

到目前为止,您尚未使用内置函数或库来解决该问题。

答案 3 :(得分:0)

从一个堆叠的顶部取出并放到一个新堆栈的顶部 - 它是相反的:

list_rev(L, R) :-
    list_rev(L, [], R). % "[]" is the new stack

list_rev([], R, R). % When original stack is empty the new stack is done
list_rev([X|Xs], Ys, R) :- % "[X|Xs]" takes X from the top of Xs
    list_rev(Xs, [X|Ys], R). % ... and puts it on the top of Ys

?- list_rev([a, [b, c], d, [e, f]], R).
R = [[e, f], d, [b, c], a].