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.

We have towns with temperatures and dates. And we need to add them to the correct list. I think the rules is right but when I run it with TkEclipse I get this:

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

and as I watched at the tracer of program take only the first temperature(thessaloniki,january,24,1). 2 times and not the second one temperature(thessaloniki,january,25,-2).
If change the name of the second to thessaloniki2 run ok but the exercise gives it with the same name.

false
  • 10,264
  • 13
  • 101
  • 209
xiamtos
  • 69
  • 1
  • 6

2 Answers2

3

Why do you have once the goal temperature(H,january,_,Te) and once the goal temperature(H,january,25,Te)? I assume you mean that both should be the same goal.

But there are other stylistic remarks. I just take the first rule:

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

append/3 is much less used in Prolog than you might expect. You could literally replace append([X],L4,L2) by L2 = [X|L4]. But you can put it even further and move the (=)/2-goals to the head:

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

Not enough: A program as this, will work, but will produce an enormous overhead. See:

In this case, move the interesting tests to the top:

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

This will avoid the exponential overhead. (Exponential in the length of the first argument's list).

The very last rule in your program should probably read: If there is no data for this city, ignore it. Thus \+ temperature(H,january,_,_).

Community
  • 1
  • 1
false
  • 10,264
  • 13
  • 101
  • 209
  • L2 list must have the names of towns at any day of january was above 0 -> temperature(H,january,_,Te) Te>0 , and L3 list name's of town's at 25 january under 0 -> temperature(H,january,25,Te) Te<0 . i use append because we didn't learn something else. – xiamtos Mar 22 '13 at 11:07
0

Because you don't state clearly your goal, we are left with guessing from the code snippet. I think you're missing 'filter' values: I'll add as Mon,Day to enforce proper selection from declared facts.

Consider using available control predicates, and avoid 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([], _, _, [], []).

yields

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

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

Note how to avoid append/3: construct a list consing in the appropriate list 'returned' by recursive call. Thanks to Prolog unification, we can do even if the call is 'yet to come'.

I think the resulting code is tail recursive, an efficiency improvement.

HTH

edit Now an equivalent program, but (IMHO) nicer

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).

edit after comments...

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([], [], []).

yields

A = [katerini, thessaloniki],
B = [].
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Sorry for that, i think it appears from the rules. L2 list must have the names of towns at any day of january was above 0, and L3 list name's of town's at 25 january under 0 . – xiamtos Mar 22 '13 at 10:59
  • My problem is tha if you put temp([thessaloniki,thesasloniki],L2,L3). for these two events temperature(thessaloniki,january,24,1), temperature(thessaloniki,january,25,-2). theoretically the list must be L2= thessaloniki for temperature>0 and L3=thessaloniki for temperature<0 and day==25 but the result is L2= thessaloniki,thesaloniki and L3=[] empty , and that's beacause take the first event temperature(thessaloniki,january,24,1) two times. Is there a problem because they have the same name? – xiamtos Mar 22 '13 at 17:38
  • Prolog make available alternatives on backtracking, so you need findall/3 or other aggregate to capture multiple values at once. – CapelliC Mar 22 '13 at 18:16
  • never mind i'ts my fault . i must call the predicates with only one thessaloniki and not two. ?- temp([thessaloniki, katerini, loutsa], L2, L3). L2 = [thessaloniki, katerini] L3 = [thessaloniki] , thanks guys and i'm sorry – xiamtos Mar 24 '13 at 14:11