Bezdepbonusu7Программирование: статьи и ответы

Вопрос

GNU Prolog - поиск в списке фактов

Автор вопроса: MattОтветов: 2

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

Если у вас есть список фактов, таких как:

%country(country, population, capital)
country(sweden, 8823, stockholm).
country(usa, 221000, washington).
country(france, 56000, paris).
country(denmark, 3400, copenhagen).

%city(city, country, population)
city(lund, sweden, 88).
city(new_york, usa, 5000).
city(paris, usa, 1).
city(copenhagen, denmark, 1200).
city(aarhus, denmark, 330).
city(odense, denmark, 120).
city(stockholm, sweden, 350).
city(washington, usa, 3400).
city(paris, france, 2000).
city(marseilles, france, 1000).

Я хочу найти второй по величине населенный город, которым в данном случае будет Вашингтон, США, с населением 3400 человек. Как бы вы смогли это сделать?

Спасибо.

  • Как бы вы подошли к поиску самого большого города? Anon. 15.12.2010

rulesprolog

Ответы

Ответ 1 · рейтинг 3 · Fred Foo

Чуть более короткая версия отличного ответа @sharky:

second_largest_city(Second) :-
    setof(Size/City, Country^city(City,Country,Size), Cities),
    append(_, [_/Second, _], Cities).

setof объединяет findall и sort. Мы собираем Size/City пар, чтобы они автоматически сортировались по размеру. Конструкция X^Goal вводит экзистенциально квантифицированную переменную X (например, x в логике первого порядка).

Ответ 2 · рейтинг 4 · Community

Попробуйте это для размера:

second_largest_city(City) :-
    findall(Size, city(_, _, Size), Sizes),
    sort(Sizes, SortedSizes),
    append(_, [Size2, _], SortedSizes),
    city(City, _Country, Size2).

Объяснение. findall/3 находит размеры всех city/3 фактов, которые отсортированы в возрастающем порядке по sort/2 с удалением дубликатов. Вызов шаблона append/3 соответствует разделению отсортированного списка SortedSizes на две части; список любого размера (_) и остаток длины два ([Size2, _]) - это связывает переменную Size2 со вторым по величине размером города из city/3 фактов. Наконец, все города с этим размером расположены среди city/3 фактов и привязаны к выходным данным.

Примечание. Обычно это не будет работать должным образом, если ваша встроенная функция для sort/2 не удаляет дубликаты, потому что это оставляет открытой возможность того, что city/3 фактов с более чем одним равный максимум вернет только максимум (самый большой). Эта реализация, использующая append/3 для поиска предпоследнего элемента отсортированного списка размеров, также предполагает sort/2 отсортированные числа в порядке возрастания.

Кроме того, наконец, обратите внимание, что это полностью потерпит неудачу, если имеется менее двух city/3 фактов - но это, вероятно, нормально, учитывая, что предикат ищет "второй по величине" город, и, строго говоря, не было бы ни одного, если бы не было действительно как минимум два города в БД с разными размерами. Если это проблема, вы можете просто написать больше предложений для second_largest_city/1, чтобы справиться с таким случаем.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы