Как отсортировать список возрастов в прологе? - PullRequest
2 голосов
/ 11 марта 2012

Я пытаюсь упорядочить список родственников по возрасту - от самого высокого до самого низкого в Прологе:

born(kate,date(11,2,1960)).
born(marc,date(11,2,1961)).
born(I,date(9,3,1962)).
born(michel,date(24,4,1963)).
born(harry,date(26,5,1964)).
born(jess,date(16,1,1965)).
born(ruth,date(26,9,1966)).
born(fran,date(4,3,1967)).

Результатом должен быть один список: [kate,marc,I,michel,harry,jess,ruth,fran].

Я пытаюсь этот фрагмент кода @CapelliC:

pairs_values([], []).
pairs_values([_-V|T0], [V|T]) :-
    pairs_values(T0, T).

by_date(Sorted) :-
  findall(Date-Person, born(Person,Date), List),
  keysort(List, Pairs),
  pairs_values(Pairs, Sorted).

Но этот код не упорядочивает его. Мне нужно сделать это в Ciao Prolog.

Ответы [ 2 ]

2 голосов
/ 18 января 2016

TL; DR: Последовательность, которую вы получаете , сортируется , но по критерию сортировки, которого вы не ожидали!

Давайте запустим CiaoПролог и попытайтесь воспроизвести странное поведение, которое наблюдал ОП!

$ ciao
Ciao 1.14.2-13646: Mon Aug 15 10:15:33 CEST 2011
?- compile(dmy_vs_ymd).
{Reading /home/stefan/Prolog/dmy_vs_ymd.pl
WARNING: (lns 3-3) [I] - singleton variables in born/2
}
yes
?- by_date(S).
S = [fran,_,kate,marc,jess,michel,harry,ruth] ? ;
no

Похоже, что каждый отдельный элемент неуместен - довольно существенная разница:)

  • ожидается: [kate,marc,I,michel,harry,jess,ruth,fran]
  • наблюдается: [fran,_,kate,marc,jess,michel,harry,ruth]

Давайте изменим порядок, например [fran,_,kate,marc,jess,michel,harry,ruth], и рассмотрим:

born(fran  , date(<b> 4</b>, 03, 1967)).
born(I     , date(<b> 9</b>, 03, 1962)).
born(kate  , date(<b>11</b>, 02, 1960)).%\_______________________________________________
born(marc  , date(<b>11</b>, 02, 1961)).%/  equal primary & secondary, different tertiary
born(jess  , date(<b>16</b>, 01, 1965)).
born(michel, date(<b>24</b>, 04, 1963)).
born(harry , date(<b>26</b>, 05, 1964)).%\____________________________________
born(ruth  , date(<b>26</b>, 09, 1966)).%/  equal primary, different secondary
%                 ^^  ^^  ^^^^
%                 ||  ||  ||||
%                 ||  ||  \+++------- tertiary sorting criterion
%                 ||  ||
%                 ||  \+------------ secondary sorting criterion
%                 ||
%                 \+------------------ primary sorting criterion

ключ? Стандартный порядок терминов! Цитирование соответствующей части руководства Ciao Prolog :

Составные термины, упорядоченные сначала по arity,затем по имени главного функтора затем по аргументам в порядке слева направо .Напомним, что списки эквивалентны составным терминам с главным функтором '.'/2.

Рассмотрим цель findall(<b>Date</b>-Person, born(Person,Date), List) в определении by_date/1.Помещение Date перед Person в Date-Person делает его основным критерием.Для сравнения двух date/3 составных терминов используется стандартный порядок.

Чтобы определить относительное положение двух date/3 соединений в стандартном порядке терминов, Prolog использует до трех критериев:

  1. Day: Если Day имеет решающее значение, Month и Year не имеют значения.

  2. Month: если Day не имеет решающего значения, но Month является решающим, то Year не имеет значения.

  3. Year: Только если Day и Month оба нерешительны, Year даже рассматривается.

Итак, можем ли мы решитьпроблема "сортировки по возрасту"?И как?

Да! Следуйте ISO 8601 и переходите с date(<b>Day</b>,Month,<i>Year</i>) на date(<b>Year</b>,Month,<i>Day</i>)!

born(fran  ,date(1967,3, 4)).
born(I,     date(1962,3, 9)).
born(kate  ,date(1960,2,11)).
born(marc  ,date(1961,2,11)).
born(jess  ,date(1965,1,16)).
born(michel,date(1963,4,24)).
born(harry, date(1964,5,26)).
born(ruth,  date(1966,9,26)).

Образецзапрос:

?- by_date(S).
S = [kate,marc,_,michel,harry,jess,ruth,fran].

Хм ... Мы уже закончили?

  • Ожидается: [kate,marc,<b>I</b>,michel,harry,jess,ruth,fran]
  • наблюдается: [kate,marc,<b>_</b>,michel,harry,jess,ruth,fran]

Не совсем на 100% ... I - это переменная - мы на самом деле хотели постоянную;замените его атомом i.Эта переменная инкогнито была причиной получения предупреждения «синглтон-переменная», которое мы получили в начале нашего сеанса Ciao Prolog.НТН!

2 голосов
/ 11 марта 2012

Мы можем сделать это в SWi-Prolog, используя несколько встроенных функций:

by_date(Sorted) :-
  findall(Date-Person, born(Person,Date), List),
  keysort(List, Pairs),
  pairs_values(Pairs, Sorted).

edit : pair_values, это действительно просто: здесь фрагмент SWI-Prolog

%%  pairs_values(+Pairs, -Values) is det.
%
%   Remove the keys  from  a  list   of  Key-Value  pairs.  Same  as
%   pairs_keys_values(Pairs, _, Values)

pairs_values([], []).
pairs_values([_-V|T0], [V|T]) :-
    pairs_values(T0, T).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...