【问题标题】:Is it possible to reverse a list with only two arguments?是否可以反转只有两个参数的列表?
【发布时间】:2011-11-08 04:56:25
【问题描述】:

是否可以在 Prolog 中仅使用两个参数来反转列表?如:

reverse_list(List, Reversed).

这不是家庭作业,我正在七周内阅读七种编程语言,我很好奇。

通过三个参数,您可以使用累加器(很像函数式编程):

reverseList([], Accumulator, Accumulator).
reverseList([Head|Tail], Accumulator, Solution) :-
  reverseList(Tail, [Head|Accumulator], Solution).
reverseList(List, Solution) :-
  reverseList(List, [], Solution).

澄清:我看到了一个带有附加的解决方案,我想知道你是否可以在没有其他 prolog 函数的情况下做到这一点

【问题讨论】:

  • 请不要在标题中添加伪标签。这就是标签的用途。

标签: list prolog


【解决方案1】:

确定:

reverseList([[], Accumulator, Accumulator]).
reverseList([[Head|Tail], Accumulator, Solution]) :-
  reverseList([Tail, [Head|Accumulator], Solution]).
reverseList([List, Solution]) :-
  reverseList([List, [], Solution]).

edit: 实际上只有一个 :b

一种不作弊的方法:

reverse([],[]).
reverse([H|T],L):-
    reverse(T,R),
    append(R,[H],L).

问题在于性能会很差:您将递归列表,并且为每个元素执行一次 append/3。 使用 time/1 和 1,000,000 个元素的随机列表:

accumulator:    % 2,000,003 inferences, 0.652 CPU in 0.652 seconds (100% CPU, 3066292 Lips)
arity-2         % 1,000,003 inferences, 0.178 CPU in 0.178 seconds (100% CPU, 5602426 Lips)

【讨论】:

    【解决方案2】:

    您可以编写一个带有两个参数的rev_list 函数:

    rev_list([], []).
    rev_list([Head|Tail], Reversed) :- rev_list(Tail, TailReversed), 
                                           append(TailReversed, [Head], Reversed).
    

    如果是函数式编程,可能你更熟悉这个函数:

    rev x::xs = rev xs @ [x]
    

    但是,您应该注意到 3 参数版本是首选,因为它是尾递归的。

    【讨论】:

    • 我看到了一个带有附加的解决方案,我想知道你是否可以在没有其他 prolog 函数的情况下做到这一点。
    【解决方案3】:

    我知道我迟到了,但有一种方法可以做到这一点,而无需“作弊”或使用append

    rev([], []).
    rev([Head], [Head]).
    rev([Head|Tail], [RHead|RTail]) :-
      rev(Tail, [RHead|RMid]),
      rev(RMid, Mid),
      rev([Head|Mid], RTail).
    

    效率不是很高(O(3^n)time),但它很优雅,甚至可以用于定理证明。

    【讨论】:

    • @repeat 因为它不使用任何外部函数,所以很容易看出它做了什么。我参加了一个使用ACL2 的课程,我记得我们让ACL2 证明这个版本等同于追加版本和尾递归版本。然后我们可以在我们的程序中使用高效的尾递归,但是在证明程序的正确性时让 ACL2 用这个或附加的替换它(取决于哪个更方便)。
    猜你喜欢
    • 2017-03-10
    • 2018-07-26
    • 1970-01-01
    • 2011-05-08
    • 2014-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    相关资源
    最近更新 更多