mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 01:43:35 +00:00
90 lines
2.6 KiB
Mathematica
90 lines
2.6 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=4 sw=4 et ft=mercury
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Test whether list.sort is stable.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module stable_sort.
|
|
:- interface.
|
|
:- import_module io.
|
|
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
:- implementation.
|
|
|
|
:- import_module bool.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module random.
|
|
:- import_module random.sfc16.
|
|
|
|
main(!IO) :-
|
|
generate_random_list(List),
|
|
% io.write(List),
|
|
% io.nl,
|
|
% io.write(sort(List) `with_type` list({int, int})),
|
|
% io.nl,
|
|
is_sort_stable(List, Stable),
|
|
(
|
|
Stable = yes,
|
|
io.write_string("list.sort/3 appears stable\n", !IO)
|
|
;
|
|
Stable = no,
|
|
io.write_string("list.sort/3 is not stable\n", !IO)
|
|
).
|
|
|
|
:- pred generate_random_list(list({int, int})::out) is det.
|
|
|
|
generate_random_list(List) :-
|
|
RandomState0 = random.sfc16.init,
|
|
% We generate random integers from 0 to 9. The list length must be
|
|
% large enough to ensure that there are plenty of duplications,
|
|
% otherwise the test is trivial.
|
|
Count = 100,
|
|
generate_random_list_2(Count, [], List, RandomState0, _).
|
|
|
|
:- pred generate_random_list_2(int::in,
|
|
list({int, int})::in, list({int, int})::out,
|
|
RandomState::in, RandomState::out) is det <= random(RandomState).
|
|
|
|
generate_random_list_2(Count, List0, List, !RandomState) :-
|
|
( if Count > 0 then
|
|
uniform_int_in_range(0, 9, R1, !RandomState),
|
|
uniform_int_in_range(0, 9, R2, !RandomState),
|
|
generate_random_list_2(Count - 1, [{R1, R2} | List0], List,
|
|
!RandomState)
|
|
else
|
|
List = List0
|
|
).
|
|
|
|
:- pred is_sort_stable(list({int, int})::in, bool::out) is det.
|
|
|
|
is_sort_stable(Unsorted, Stable) :-
|
|
% If the sort is stable, then sorting on the second component
|
|
% followed by sorting on the first component *should* give a
|
|
% fully sorted result.
|
|
list.sort(compare_second, Unsorted, SortedOnSecond),
|
|
list.sort(compare_first, SortedOnSecond, SortedOnSecondThenFirst),
|
|
|
|
% Check whether the result is fully sorted.
|
|
list.sort(Unsorted, Sorted),
|
|
( if SortedOnSecondThenFirst = Sorted then
|
|
Stable = yes
|
|
else
|
|
Stable = no
|
|
).
|
|
|
|
:- pred compare_first({int, int}::in, {int, int}::in, comparison_result::out)
|
|
is det.
|
|
|
|
compare_first({A, _}, {B, _}, Res) :-
|
|
compare(Res, A, B).
|
|
|
|
:- pred compare_second({int, int}::in, {int, int}::in, comparison_result::out)
|
|
is det.
|
|
|
|
compare_second({_, A}, {_, B}, Res) :-
|
|
compare(Res, A, B).
|