Пролог - максимальное значение в рекурсии - PullRequest
1 голос
/ 06 апреля 2020

Здравствуйте, я делаю работу для школы и пытаюсь получить максимальное число, которое возвращается с помощью рекурсии. Позвольте мне объяснить лучше с примерами:

У меня есть этот предикат:

li(_, []).
li(NAME, [H|T]) :- 
   find(NAME, H, Occur),
   li(NAME, T).

li(NAME) :- 
   findall(T, pri(name(T), _, _, _), Info),
   li(NAME, Info).

Предикат в строке 2 (найти), что он делает, давая имя и некоторую другую информацию, которую он вернет мне номер (Происходит). То, что я пытаюсь сделать, это узнать, каково наибольшее число (Occur) во всей рекурсии.

Ниже я попытался сделать несколько сравнений, но это не работает, он говорит, что Высшее не определено, Я знаю, потому что это не имеет никакого значения, связанного с ним, но я не знаю, как это сделать.

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

Цель состоит в том, чтобы написать число в конце строки 3. Кто-нибудь знаете, что я могу сделать, чтобы это исправить? Спасибо.

РЕДАКТИРОВАТЬ

Я сделал еще одну попытку и сделал это:

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

Это не вызывает никаких ошибок, но ничего не происходит, возвращается false и ничего не печатается.

EDIT2

Спасибо @David Tonhofer, теперь я могу получить самое высокое число. Но то, что я действительно хочу, это имя, которое ассоциируется с этим высоким числом.

li(NAME, [H|T], Highest, X) :- 
   find(NAME, H, Occur), 
   li(NAME, T, Temp), 
   Highest is max(Temp,Occur), X = ??.

Я шел шаг за шагом и сначала пытался получить наибольшее число, затем получаю имя, но теперь с МАКСОМ я не думаю, что я могу это знать.

Сначала я подумал что-то вроде этого:

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

Ответы [ 2 ]

2 голосов
/ 06 апреля 2020

В SWI-Prolog библиотека ( агрегат ) предназначена для обеспечения SQL -подобного решения вашей проблемы:

?- 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).
2 голосов
/ 06 апреля 2020

Вот проблема:

li(NAME, [H|T], Highest) :- 
   find(NAME, H, Occur), 
   li(NAME, T, Temp), 
   Temp < Occur, 
   Temp is Occur,
   Highest is Temp.

Это означает:

  • Убедитесь, что Temp < Occur, вернитесь назад, чтобы попробовать что-то еще, если нет.
  • Затем объедините цифры c, значения Occur и Temp. Поскольку Temp уже содержит некоторое значение, это то же самое, что и проверка того, равны ли Occur и Temp одинаковые значения, и возврат в обратном направлении, чтобы попробовать что-то еще, если нет.
  • Затем объедините числа c значения Highest и Temp.

Вы, кажется, хотите, чтобы Highest принял значение max(Occur,Temp).

В этом случае:

li(NAME, [H|T], Highest) :- 
   find(NAME, H, Occur), 
   li(NAME, T, Temp), 
   Highest is max(Temp,Occur).

This

  1. Вычисляет max(Temp,Occur) (работает, только если известны значения Temp и Occur. эта точка)
  2. Объединяет результат с Highest. Если Highest все еще переменная fre sh, это похоже на присваивание. В противном случае, если Highest уже содержит что-то, это похоже на сравнение.

Приложение

Чтобы получить «Имя», связанное с полученным максимальным значением, выполните таким же образом:

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.

Для предиката-помощника вы также можете написать, возможно, более четко:

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...