Я ищу быстрый способ сортировки списка в обратном порядке в Прологе.Алгоритмически он должен работать так же быстро, как и стандартная сортировка, но варианты, которые я придумала, гораздо медленнее, по очевидным причинам.
Предикат rsort1/2
сортирует и затем переворачивает.
rsort1(L1, L2) :-
sort(L1, Tmp),
reverse(Tmp, L2).
Предикат rsort2/2
использует predsort/3
с пользовательским компаратором.
rsort2(L1, L2) :-
predsort(reverse_compare, L1, L2).
reverse_compare(Delta, E1, E2) :-
compare(Delta, E2, E1).
Чтобы проверить их производительность, я создал огромный случайный список, подобный этому:
?- Size = 1234567,
findall(N, (between(1, Size, _), N is random(Size)), Ns),
assert(test_list(Ns)).
Size = 1234567,
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258|...].
Этовремя выполнения для стандартного sort
:
?- test_list(Ns), time(sort(Ns, NsS)).
% 2 inferences, 7.550 CPU in 8.534 seconds (88% CPU, 0 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [0, 1, 3, 5, 8, 10, 12, 14, 16|...].
... для rsort1
:
?- test_list(Ns), time(rsort1(Ns, NsS)).
% 779,895 inferences, 8.310 CPU in 9.011 seconds (92% CPU, 93850 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [1234564, 1234563, 1234562, 1234558, 1234557, 1234556, 1234555|...].
... и для rsort2
:
?- test_list(Ns), time(rsort2(Ns, NsS)).
% 92,768,484 inferences, 67.990 CPU in 97.666 seconds (70% CPU, 1364443 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [1234564, 1234563, 1234562, 1234558, 1234557, 1234556, 1234555|...].
Могу ли я сделать лучше, чем rsort1
и rsort2
по скорости?