2
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 运行正常,但练习给出了相同的名称。

4

2 回答 2

3

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

但还有其他文体评论。我只接受第一条规则:

温度([H|T],L2,L3):-
   温度(T,L4,L5),
   温度(H,一月,_,Te),
   Te>0,
   附加([H],L4,L2),
   L3=L5。

append/3在 Prolog 中的使用比你想象的要少得多。您可以从字面上替换append([X],L4,L2)L2 = [X|L4]. 但是您可以更进一步,将(=)/2-goals 移到头部:

温度([H|T],[H|Ps],Ms):-
   温度(T,Ps,Ms),
   温度(H,一月,_,Te),
   Te>0。

还不够:这样的程序可以工作,但会产生巨大的开销。看:

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

温度([H|T],[H|Ps],Ms):-
   温度(H,一月,_,Te),
   Te>0,
   温度(T,Ps,Ms)。

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

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

于 2013-03-22T00:24:38.523 回答
0

因为您没有明确说明您的目标,所以我们只能从代码片段中猜测。我认为您缺少“过滤器”值:我将添加Mon,Day以强制从已声明的事实中进行正确选择。

考虑使用可用的控制谓词,并避免 append/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].

请注意如何避免 append/3:consing在通过递归调用“返回”的适当列表中构造一个列表。感谢 Prolog 的统一,即使呼叫“尚未到来”,我们也可以做到。

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

高温高压

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

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 = [].
于 2013-03-22T09:07:37.433 回答