在 Prolog 中,如何对用符号和谓词链表示的偶数和奇数进行排序?

In Prolog, how to sort even and odd numbers represented with symbols and chains of predicates?

标题可能比较模糊,直接看代码

number(one, odd).
number(two, even).
number(three, odd).
number(four, even).
number(five, odd).

greaterThan(five, four).
greaterThan(four, three).
greaterThan(three, two).
greaterThan(two, one).

if_larger(A,B):- elder_than(A,B).
if_larger(A,B):- elder_than(A,X),greaterThan(X,B).

even(A):- number(A, even).
odd(A):- number(A, odd).

largest(A):-
    not(greaterThan(_,A)).

largestEven(A):-
    even(A),
    not((if_larger(X,A), even(X))).

largestOdd(A):-
    odd(A),
    not((if_larger(X,A), odd(X))).

如何按以下顺序对数字进行排序:一、三、五、二、四。

我认为解决方案应该是下面的形式,但是我想不出来。

next(A, Next):- 
    odd(A), odd(Next),
    ...

next(A, Next):- 
    even(A), even(Next),
    ...

next(A, Next):- 
    odd(A), even(Next),
    ...

或者,是否可以生成一个列表,例如[一、三、五、二、四]。

我会回答我自己的问题。这个想法是使用 final/3 构建所有数字的列表,然后对数字列表应用插入排序。

实施

number(five, odd).
number(one, odd).
number(two, even).
number(three, odd).
number(four, even).

greaterThan(five, four).
greaterThan(four, three).
greaterThan(three, two).
greaterThan(two, one).

even(A):- number(A, even).
odd(A):- number(A, odd).

is_larger(A,B):- greaterThan(A,B).
is_larger(A,B):- greaterThan(A,X),is_larger(X,B).

% the order considered even and odd
% which is odd before even, small before large
in_order(A,B):- odd(A), even(B).
in_order(A,B):- odd(A), odd(B), is_larger(B,A).     % smaller numbers comes first
in_order(A,B):- even(A), even(B), is_larger(B,A).   % smaller numbers comes first


% apply insertion sort on A 
insertion_sort(A,B):- sort_helper(A, [], B).
sort_helper([], OldList, OldList).
sort_helper([H|T], OldList, Result):- insert(H, OldList, NewList), sort_helper(T, NewList, Result).

% insert(A,L,Result) put A into L 
insert(A, [], [A]).
insert(A, [H|T], [A,H|T]):- in_order(A,H).
insert(A, [H|T], [H|NewList]):- not(in_order(A,H)), insert(A, T, NewList).

% Interface
oddEvenSortedList(OddEvenSortedList):- findall(A, number(A,_), Numbers), insertion_sort(Numbers, OddEvenSortedList).

结果

?- ['number.pl'].
true.

?- oddEvenSortedList(OddEvenSortedList).
OddEvenSortedList = [one, three, five, two, four].

这道题实际上是我学校作业的修改版。最初的问题是 Prolog 中的 Royal Family Succession。问了很多朋友怎么解决这个问题,终于得到了这个解决方案。我也会post原来的问题。

The old Royal succession rule states that the throne is passed down along the male line according to the order of birth before the consideration along the female line – similarly according to the order of birth. Queen Elizabeth, the monarch of United Kingdom, has four offsprings; namely:- Prince Charles, Princess Ann, Prince Andrew and Prince Edward – listed in the order of birth.