我认为@CapelliC制作的比较已经被删除,这是误导性的。原帖要求一个谓词来比较两个列表并检查它们是否相同,除了最后两个元素可能出现交换(这与只交换单个列表的最后两个元素的谓词是不同的)。因此,更公正的比较应该使用两个实例化的列表作为输入来调用要比较的谓词。
我的建议是将perf_belt/3
修改如下:
:- module(last2swap_perf, [cmp/2]).
:- meta_predicate perf_belt(+,+,3).
last2swap_app2(A,B,[U,V]):-
append([C,[U,V]],A),
append([C,[V,U]],B).
last2swap_app3(A,B,[U,V]):-
append(C,[U,V],A),
append(C,[V,U],B).
lastTwoReversed(L1, L2, [X1,X2]) :-
reverse(L1, [X1,X2|Rest]),
reverse(L2, [X2,X1|Rest]).
swap_last_2([Elem1, Elem2|Tail], SwappedLst, Last2) :-
swap_last_2_(Tail, Elem1, Elem2, [], RevSwappedLst, Last2),
reverse(RevSwappedLst, SwappedLst).
swap_last_2_([], Elem1, Elem2, SoFar, [Elem1, Elem2|SoFar], [Elem2, Elem1]).
swap_last_2_([Head|Tail], Elem1, Elem2, SoFar, SwappedLst, Last2) :-
swap_last_2_(Tail, Elem2, Head, [Elem1|SoFar], SwappedLst, Last2).
perf_belt(NRep, LList, Pred) :-
make_lists(LList, List1, List2),
time( forall(between(1, NRep, _),
call(Pred, List1, List2, _)) ).
make_lists(N, List1, List2) :-
N1 is N - 1,
N2 is N - 2,
numlist(1, N2, Prefix),
append(Prefix, [N1, N], List1),
append(Prefix, [N, N1], List2).
cmp(NRep,LList) :-
perf_belt(NRep,LList,last2swap_app2),
perf_belt(NRep,LList,last2swap_app3),
perf_belt(NRep,LList,lastTwoReversed),
perf_belt(NRep,LList,swap_last_2).
更公平的结果 在运行SWI-Prolog 8.4.1版本时,我们可以看到双重反转并不那么糟糕。
?- cmp(100, 100).
true.
?- cmp(100, 1000).
true.
?- cmp(1000, 1000).
true.