我们想检查一个元素是否出现在列表的最后一个,我们有这个prolog程序对我来说很明显:
last(X,[X]).
last(X,[_|L]):-
last(X,L).
但我们的老师给了我们另一个解决方案,他说它更优化,有它:
last(X,[X]).
last(X,[_,Y|L]):-
last(X,[Y|L]).
为什么第二种解决方案更优化?
答案 0 :(得分:3)
这一切都取决于你衡量的是什么。显然你的老师会做@Armatorix在答案中所做的事情,并简单地计算最后/ 2的调用。但实际上,你的教师版本可能在所有Prolog系统上都会变慢,甚至会慢得多:
% Simple version:
?- length(Xs,10000000), time(last(X,Xs)).
% 10,000,000 inferences, 0.852 CPU in 0.852 seconds (100% CPU, 11735202 Lips)
% "Optimized" version
?- length(Xs,10000000), time(last(X,Xs)).
% 9,999,999 inferences, 4.436 CPU in 4.437 seconds (100% CPU, 2254074 Lips)
要明白原因,你必须意识到“优化”版本是
的语法糖last(X,[X]).
last(X,[_,Y|L]):-
YL = [Y|L], % this takes time!
last(X,YL).
答案 1 :(得分:2)
好的,理论上他是对的。
使用他的方法,我们不会检查列表中始终包含的最后一个空元素。
用2个东西很容易检查,第一个是time
函数,另一个是trace
。这是列表(lastX是你的老师版本,而lastY是你的):
?- time(lastY(5,[1,2,3,4,5])).
% 5 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 1743983 Lips)
true
?- time(lastX(5,[1,2,3,4,5])).
% 4 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 194203 Lips)
true .
?- time(lastX(6,[1,2,3,4,5])).
% 6 inferences, 0.000 CPU in 0.000 seconds (87% CPU, 279382 Lips)
false.
?- time(lastY(6,[1,2,3,4,5])).
% 7 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 335008 Lips)
false.
[trace] ?- lastY(6,[1,2,3,4,5]).
Call: (7) lastY(6, [1, 2, 3, 4, 5]) ? Unknown option (h for help)
Call: (7) lastY(6, [1, 2, 3, 4, 5]) ? creep
Call: (8) lastY(6, [2, 3, 4, 5]) ? creep
Call: (9) lastY(6, [3, 4, 5]) ? creep
Call: (10) lastY(6, [4, 5]) ? creep
Call: (11) lastY(6, [5]) ? creep
Call: (12) lastY(6, []) ? creep
Fail: (12) lastY(6, []) ? creep
Fail: (11) lastY(6, [5]) ? creep
Fail: (10) lastY(6, [4, 5]) ? creep
Fail: (9) lastY(6, [3, 4, 5]) ? creep
Fail: (8) lastY(6, [2, 3, 4, 5]) ? creep
Fail: (7) lastY(6, [1, 2, 3, 4, 5]) ? creep
false.
[trace] ?- lastX(6,[1,2,3,4,5]).
Call: (7) lastX(6, [1, 2, 3, 4, 5]) ? creep
Call: (8) lastX(6, [2, 3, 4, 5]) ? creep
Call: (9) lastX(6, [3, 4, 5]) ? creep
Call: (10) lastX(6, [4, 5]) ? creep
Call: (11) lastX(6, [5]) ? creep
Fail: (11) lastX(6, [5]) ? creep
Fail: (10) lastX(6, [4, 5]) ? creep
Fail: (9) lastX(6, [3, 4, 5]) ? creep
Fail: (8) lastX(6, [2, 3, 4, 5]) ? creep
Fail: (7) lastX(6, [1, 2, 3, 4, 5]) ? creep
false.