是否可以仅使用两个参数来反转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函数的情况下做到这一点
答案 0 :(得分:5)
确定:
reverseList([[], Accumulator, Accumulator]).
reverseList([[Head|Tail], Accumulator, Solution]) :-
reverseList([Tail, [Head|Accumulator], Solution]).
reverseList([List, Solution]) :-
reverseList([List, [], Solution]).
编辑:实际上只有一个:b
非作弊方法:
reverse([],[]).
reverse([H|T],L):-
reverse(T,R),
append(R,[H],L).
问题是性能会非常糟糕:你将在列表中进行递归,对于每个元素,你会做一个追加/ 3。 使用时间/ 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)
答案 1 :(得分:3)
您可以使用两个参数编写rev_list
函数:
rev_list([], []).
rev_list([Head|Tail], Reversed) :- rev_list(Tail, TailReversed),
append(TailReversed, [Head], Reversed).
如果它在函数式编程中,你可能更熟悉这个函数:
rev x::xs = rev xs @ [x]
但是,您应该注意到3参数版本是首选版本,因为它是尾递归的。
答案 2 :(得分:2)
我知道我迟到了,但有一种方法可以在不“欺骗”或使用append
的情况下做到这一点:
rev([], []).
rev([Head], [Head]).
rev([Head|Tail], [RHead|RTail]) :-
rev(Tail, [RHead|RMid]),
rev(RMid, Mid),
rev([Head|Mid], RTail).
效率不高(O(3^n)
时间),但它很优雅,甚至可用于定理证明。