【问题标题】:Reverse list of lists反向列表列表
【发布时间】:2013-11-23 16:06:03
【问题描述】:

我的序言代码有问题。我需要反转列表的所有原子元素。

示例:[1,2,[3,4]] -> [[4,3],2,1]

我的解决方案:

myReverse([], []).
myReverse([H|T], X) :- myReverse(T, RT), myAppend(RT, H, X).

但它只给我:[[3,4],2,1] 我想,如果它不是原子的,我需要使用 is_list 函数和递归调用列表......但我被卡住了......你们知道怎么写吗?

【问题讨论】:

  • spoj/3 是什么?我对 SPhere Online Judge 很熟悉,但是一提到 Prolog,我就迷路了……
  • 我已将其重命名为 myAppend,函数加入两个列表并将结果保存到 X。

标签: list prolog reverse


【解决方案1】:

几乎。考虑这个解决方案:

myReverse([], []) :- !.

myReverse([H|T], X) :-
    !,
    myReverse(H, NewH),
    myReverse(T, NewT),
    append(NewT, [NewH], X).

myReverse(X, X).

第一个子句是基本情况,其中包括一个删减 (!) 以排除由于最后一个子句而留下的选择。

第二个子句反转了头部H,它可能是一个原子或一个列表。如果H 是原子,则切割后的递归子目标使用最后一个子句求值,并且原子不变地通过。如果H 是一个列表,则使用第二个子句对其进行评估,并将所有元素反转。下一个子目标对列表的其余部分(尾部,T)执行相同的操作,然后最终使用内置的append/3 连接。请注意,新的 head 元素 NewH 是单数的,因此需要根据 append/3 的定义将其添加到单例列表结构中作为 [NewH] 对列表进行操作。

最后一个子句不变地传递所有其他事物(即原子、数字等 - 任何不是列表或变量的事物)。

【讨论】:

    【解决方案2】:
    revall(L, Y) :-
        revall(L, [], Y).
    revall([], Y, Y).
    revall([H|T], T2, Y) :-
        is_list(H),!,
        revall(H, Hr),
        revall(T, [Hr|T2], Y).
    revall([H|T], T2, Y) :-
        revall(T, [H|T2], Y).
    

    这里没有附加

    【讨论】:

    • +1:这是一个不错的累加器版本,与我提议的版本相比,它会使用更少的堆栈空间(不是尾递归)。如果您使用模式匹配而不是通过在revall/3 的第二个子句中将H 更改为[H|Hs],您甚至可以替换is_list/1 调用(并留下剪辑),那么根本不需要内置插件.
    猜你喜欢
    • 2021-12-25
    • 2011-11-12
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    相关资源
    最近更新 更多