Макс из значений, определенных в пунктах пролога - PullRequest
1 голос
/ 09 ноября 2009

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

cat(sassy, 5).
cat(misty, 3).
cat(princess, 2).

Моей первой мыслью было: «Хм, самая старая кошка - та, для которой не существует старшая». Но я не смог перевести это на пролог.

oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X \= Y, \+ AgeX < AgeY, print(Y).

Это все еще ошибочно совпадает с "туманным". Какой правильный способ сделать это? Есть ли какой-то способ более прямой итерации по возрастам, чтобы выбрать max?

Ответы [ 5 ]

6 голосов
/ 10 ноября 2009

Одним из способов является

oldest(X) :- cat(X, AgeX), \+ Y^(cat(Y, AgeY), Y \= X, AgeX < AgeY).

Вы также можете использовать setof / 3, чтобы получить список всех кошек и получить максимум из этого.

4 голосов
/ 10 ноября 2009

Кошка самая старая, если это кошка, и нет кошки старше ее. Давайте напишем это в Прологе:

oldest(X):- cat(X, _), not( thereAreOlders(X)), !.
thereAreOlders(X):- cat(X, N), cat(C, M), C\=X, M > N.

Если вы проконсультируетесь:

?- oldest(X).
X = sassy.
2 голосов
/ 10 ноября 2009

Вот решение, которое перебирает все решения, всегда записывая решение, которое лучше предыдущего. В итоге возвращается лучшее решение.

Запись выполняется с использованием assert/1, вы также можете использовать глобальную переменную без возможности возврата назад, если ваш Prolog предоставляет это (SWI-Prolog делает).

Преимущество этого подхода состоит в том, что каждое решение рассматривается только один раз, то есть сложность O (n). Поэтому, хотя он выглядит хуже, чем решение Starblue, он должен работать лучше.

% Data
cat(sassy, 5).
cat(misty, 3).
cat(miisu, 10).
cat(princess, 2).

% Interface
oldest_cat(Name) :-
    loop_through_cats,
    fetch_oldest_cat(Name).

loop_through_cats :-
    cat(Name, Age),
    record_cat_age(Name, Age),
    fail ; true.


:- dynamic current_oldest_cat/2.

record_cat_age(Name, Age) :-
    current_oldest_cat(_, CAge),
    !,
    Age > CAge,
    retract(current_oldest_cat(_, _)),
    assert(current_oldest_cat(Name, Age)).

record_cat_age(Name, Age) :-
    assert(current_oldest_cat(Name, Age)).


fetch_oldest_cat(Name) :-
    retract(current_oldest_cat(Name, _Age)).

Пример использования:

?- oldest_cat(Name).

Name = miisu

Miisu - типичное эстонское имя кошки. ;)

0 голосов
/ 26 марта 2013

В стилистическом плане - здесь есть несколько разных подходов (некоторые очень элегантные, другие более «читабельные»). Если вы новичок - выбрали свой собственный, предпочтительный способ ведения дел, но неэффективный.

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

0 голосов
/ 10 ноября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...