Я просто думаю функционально:
Очевидно, predsort - это предикат для использования. Это на самом деле не ISO, а от library(list)
my_cmp(X,L,R) :-
atom_length(L,Llen),atom_length(R,Rlen),
((Llen < Rlen) -> X = '>' ;
(Llen > Rlen) -> X = '<' ;
X = '=').
sort_desc_len(L,S) :- predsort(my_cmp,L,S).
В зависимости от того, как вычисляется atom_length/2
(т.е. в зависимости от того, нужно ли просто получить скрытую длину значение вместо того, чтобы пересечь строку атома), это может быть довольно быстро.
:- begin_tests(sort_desc_len).
test(empty) :- sort_desc_len([],[]).
test(nop) :- sort_desc_len([aaa,bb,c],[aaa,bb,c]).
test(reverse) :- sort_desc_len([a,bb,ccc],[ccc,bb,a]).
test(duplicates) :- sort_desc_len([a,bb,bb,ccc],[ccc,bb,a]).
test(stability) :- sort_desc_len([i,j,k],[i,j,k]).
test(random) :- sort_desc_len([a,xx,fg,hhh,jk],[hhh,xx,fg,jk,a]).
test(exercise) :- sort_desc_len([a,bcd,ef,ghij],[ghij,bcd,ef,a]).
:- end_tests(sort_desc_len).
Итак, я Стадо У Лика Тесты ...
?- run_tests(sort_desc_len).
% PL-Unit: sort_desc_len ....
ERROR: user://4:87:
test stability: failed
ERROR: user://4:88:
test random: failed
. done
% 2 tests failed
% 5 tests passed
К сожалению, predsort/3
удаляет дубликаты. Абсолютно должно быть predsort/4
, указывающее, должны ли дубликаты быть гонерами.
?- sort_desc_len([i,j,k],X).
X = [i].
?- sort_desc_len([a,xx,fg,hhh,jk],X).
X = [hhh, xx, a].
FAIL.
Приложение
Менее шумно при использовании compare/3
, как предлагается в комментарии repeat .
NB compare/3
вызов с обменом длины влево и вправо.
my_cmp(X,L,R) :-
atom_length(L,Llen),
atom_length(R,Rlen),
compare(X,Rlen,Llen).
sort_desc_len(L,S) :- predsort(my_cmp,L,S).
?- run_tests(sort_desc_len).
% PL-Unit: sort_desc_len ....
ERROR: user://1:20:
test stability: failed
ERROR: user://1:21:
test random: failed
. done
% 2 tests failed
% 5 tests passed
false.