Prolog - 附加到错误列表

时间:2013-03-22 00:00:14

标签: prolog

temperature(thessaloniki,january,24,1).
temperature(thessaloniki,january,25,-2).
temperature(katerini,january,24,3).
temperature(loutsa,feb,25,1).

temp([],[],[]).
temp([H|T],L2,L3) :-
   temp(T,L4,L5),
   temperature(H,january,_,Te),
   Te>0,
   append([H],L4,L2),
   L3=L5.
temp([H|T],L2,L3) :-
   temp(T,L4,L5),
   temperature(H,january,25,Te),
   Te<0,
   append([H],L5,L3),
   L2=L4.
temp([H|T],L2,L3) :-
   temp(T,L4,L5),
   L2=L4,
   L3=L5.

我们有温度和日期的城镇。我们需要将它们添加到正确的列表中。我认为规则是正确的,但是当我用TkEclipse运行时,我得到了这个:

?- temp([thessaloniki, thessaloniki, katerini, loutsa], L2, L3).
L2 = [thessaloniki, thessaloniki, katerini]
L3 = []

当我在程序示踪器上观看时只需要第一次temperature(thessaloniki,january,24,1). 2次而不是第二次temperature(thessaloniki,january,25,-2).如果将第二个名称更改为thessaloniki2运行正常但是练习赋予它相同的名称。

2 个答案:

答案 0 :(得分:3)

为什么您有一次目标temperature(H,january,_,Te)和目标temperature(H,january,25,Te)?我认为你的意思是两者都应该是同一个目标。

但还有其他风格的评论。我只是采取第一条规则:

temp([H|T],L2,L3) :-
   temp(T,L4,L5),
   temperature(H,january,_,Te),
   Te>0,
   append([H],L4,L2),
   L3=L5.

append/3在Prolog中的使用量远低于您的预期。你可以用append([X],L4,L2)逐字取代L2 = [X|L4]。但你可以更进一步,将(=)/2 - 目标移到头上:

temp([H|T],[H|Ps],Ms) :-
   temp(T,Ps,Ms),
   temperature(H,january,_,Te),
   Te>0.

还不够:这样的程序会起作用,但会产生巨大的开销。参见:

在这种情况下,将有趣的测试移到顶部:

temp([H|T],[H|Ps],Ms) :-
   temperature(H,january,_,Te),
   Te>0,
   temp(T,Ps,Ms).

这将避免指数开销。 (第一个参数列表长度的指数)。

程序中的最后一条规则应该是:如果此城市没有数据,请忽略它。因此\+ temperature(H,january,_,_)

答案 1 :(得分:0)

因为您没有明确说明您的目标,所以我们会从代码段中猜测。我认为你错过了'过滤器'值:我将添加Mon,Day来强制从声明的事实中进行适当的选择。

考虑使用可用的control predicates,并避免追加/ 3:

temperature(thessaloniki,january,24,1).
temperature(thessaloniki,january,25,-2).
temperature(katerini,january,24,3).
temperature(loutsa,feb,25,1).

temp([H|T], Mon, Day, L2, L3) :-
   (   temperature(H, Mon, Day, Te)
   ->  (   Te > 0
       ->  L2 = [H|L4], L3 = L5
       ;   Te < 0
       ->  L2 = L4, L3 = [H|L5]
       ;   L2 = L4, L3 = L5
       )
   ;   L2 = L4, L3 = L5
   ),
   temp(T, Mon, Day, L4, L5).

temp([], _, _, [], []).

产量

?- temp([katerini, loutsa, thessaloniki],january,24,A,B).
A = [katerini, thessaloniki],
B = [].

?- temp([katerini, loutsa, thessaloniki],january,25,A,B).
A = [],
B = [thessaloniki].

注意如何避免追加/ 3:通过递归调用在“返回”的相应列表中构造列表consing。感谢Prolog统一,即使呼叫“尚未到来”,我们也能做到。

我认为生成的代码是尾递归的,提高了效率。

HTH

编辑现在是等效的程序,但是(恕我直言)更好

temp([H|T], Mon, Day, L2, L3) :-
   (   temperature(H, Mon, Day, Te)
   ->  (   Te > 0
       ->  L2/L3 = [H|L4]/L5
       ;   Te < 0
       ->  L2/L3 = L4/[H|L5]
       ;   L2/L3 = L4/L5
       )
   ;   L2/L3 = L4/L5
   ),
   temp(T, Mon, Day, L4, L5).
评论后

编辑 ...

temp([H|T], L2, L3) :-
   (   temperature(H, january, Day, Te)
   ->  (   Te > 0
       ->  L2/L3 = [H|L4]/L5
       ;   Te < 0, Day = 25
       ->  L2/L3 = L4/[H|L5]
       ;   L2/L3 = L4/L5
       )
   ;   L2/L3 = L4/L5
   ),
   temp(T, L4, L5).
temp([], [], []).

产量

A = [katerini, thessaloniki],
B = [].