Reputation:
Hello I doing a work for school and I'm trying to get the max number that is returning by a recursion. Let me explain better with examples:
I have this predicate:
li(_, []).
li(NAME, [H|T]) :-
find(NAME, H, Occur),
li(NAME, T).
li(NAME) :-
findall(T, pri(name(T), _, _, _), Info),
li(NAME, Info).
The predicate in line 2 (find), what it does is, by giving a name and some other information it will return to me a number (Occur). What I'm trying to do is to know what is the highets number (Occur) in the whole recursion.
Bellow I tried to do some comparations but it is not working, it says that Highest is not defined, I know that is becouse it don't have any value associated with it but I have not idea how to do this.
li(_, [], 0).
li(NAME, [H|T], Highest) :-
find(NAME, H, Occur),
li(NAME, T, Temp),
Temp is Occur,
Highest < Temp,
Highest is Temp.
li(NAME) :-
findall(T, pri(name(T), _, _, _), Info),
li(NAME, Info, Return),
write(Return).
The goal is to write the number in the end of line 3. Does anyone know what I can do to fix this? Thank you.
EDIT
I gave another try and done this:
li(_, [], 0).
li(NAME, [H|T], Highest) :-
find(NAME, H, Occur),
li(NAME, T, Temp),
Temp < Occur,
Temp is Occur,
Highest is Temp.
li(NAME) :-
findall(T, pri(name(T), _, _, _), Info),
li(NAME, Info, Return),
write(Return).
It doens't trigger any errors but nothing happens, a false is returned and nothing is printed.
EDIT2
Thank to @David Tonhofer, I now can get the highst number. But what I realy want is the name that is associated with that hight number.
li(NAME, [H|T], Highest, X) :-
find(NAME, H, Occur),
li(NAME, T, Temp),
Highest is max(Temp,Occur), X = ??.
I was going step by step and first trying to get the highest number then get the name, but with the MAX now I don't think I can know that.
At first I thought something like this:
li(_, [], 0).
li(NAME, [H|T], Highest, X) :-
find(NAME, H, Occur),
li(NAME, T, Temp),
Temp < Occur,
Temp is Occur,
Highest is Temp, X is NAME.
li(NAME) :-
findall(T, pri(name(T), _, _, _), Info),
li(NAME, Info, Return, X),
write(Return), write(X).
Upvotes: 1
Views: 397
Reputation: 60034
In SWI-Prolog, library(aggregate) is meant to provide an SQL-like solution for your problem:
?- L=[a:1, b:2, c:3], aggregate(max(V,N),member(N:V,L),Max).
L = [a:1, b:2, c:3],
Max = max(3, c).
Upvotes: 1
Reputation: 15338
Here is a problem:
li(NAME, [H|T], Highest) :-
find(NAME, H, Occur),
li(NAME, T, Temp),
Temp < Occur,
Temp is Occur,
Highest is Temp.
This means:
Temp < Occur
, backtrack to try something else if not.Occur
and Temp
. As Temp
already contains some value, this is the same as testing whether Occur
and Temp
are the same value, and backtrack to try something else if not. Highest
and Temp
.You seem to want Highest
to take on the value of max(Occur,Temp)
.
In that case:
li(NAME, [H|T], Highest) :-
find(NAME, H, Occur),
li(NAME, T, Temp),
Highest is max(Temp,Occur).
This
max(Temp,Occur)
(works only if the values of Temp
and Occur
.are known at that point)Highest
. If Highest
is still a fresh variable, this is similar to assignment. Otherwise, if Highest
already contains something, it is similar to comparison.To get the "Name" that is associated with the maximum value obtained, you proceed the same way:
li(Name_max, [H|T], Temp_max) :-
find(Name_from_Head, H, Temp_from_Head),
li(Name_from_Tail, T, Temp_from_Tail),
% let's just print what we have right now:
format("From the Head, we get: Name = ~w, Temp = ~w", [Name_from_Head,Temp_from_Head]),
format("From the Tail, we get: Name = ~w, Temp = ~w", [Name_from_Tail,Temp_from_Tail]),
% now a little "helper predicate" can be used for clarity
% we pass it the 4 logical variables containing names and temps
% and the 2 logical variables that have been given to "li/3"
% to fill in with the best data:
select_max(Name_from_Tail, Temp_from_Tail,
Name_from_Head, Temp_from_Head,
Name_max, Temp_max),
% and we are done; just a printing before returning for fun
format("Our current max: Name = ~w, Temp = ~w", [Name_max,Temp_max]).
% The helper predicate has two clauses for the two
% mutually exclusive alternatives
% (the "=:=" case is in the first clause, arbitrarily)
select_max(Name_from_Tail, Temp_from_Tail,
Name_from_Head, Temp_from_Head,
Name_from_Tail, Temp_from_Tail) :-
Temp_from_Tail >= Temp_from_Head.
select_max(Name_from_Tail, Temp_from_Tail,
Name_from_Head, Temp_from_Head,
Name_from_Head, Temp_from_Head) :-
Temp_from_Tail < Temp_from_Head.
For the helper predicate you could also write, perhaps more clearly:
select_max(Name_from_Tail, Temp_from_Tail,
Name_from_Head, Temp_from_Head,
Name_max, Temp_max) :-
Temp_from_Tail >= Temp_from_Head, % Guard
Name_max = Name_from_Tail, % Constrain variables to be equal!
Temp_max = Temp_from_Tail.
select_max(Name_from_Tail, Temp_from_Tail,
Name_from_Head, Temp_from_Head,
Name_max, Temp_max) :-
Temp_from_Tail < Temp_from_Head, % Guard
Name_max = Name_from_Head, % Constrain variables to be equal!
Temp_max = Temp_from_Head.
Upvotes: 1