Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
|
|
@ -0,0 +1,104 @@
|
|||
%%%-------------------------------------------------------------------
|
||||
|
||||
:- module quicksort_task_for_lists.
|
||||
|
||||
:- interface.
|
||||
:- import_module io.
|
||||
:- pred main(io, io).
|
||||
:- mode main(di, uo) is det.
|
||||
|
||||
:- implementation.
|
||||
:- import_module int.
|
||||
:- import_module list.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%%
|
||||
%%% Partitioning a list into three:
|
||||
%%%
|
||||
%%% Left elements less than the pivot
|
||||
%%% Middle elements equal to the pivot
|
||||
%%% Right elements greater than the pivot
|
||||
%%%
|
||||
%%% The implementation is tail-recursive.
|
||||
%%%
|
||||
|
||||
:- pred partition(comparison_func(T), T, list(T),
|
||||
list(T), list(T), list(T)).
|
||||
:- mode partition(in, in, in, out, out, out) is det.
|
||||
partition(Compare, Pivot, Lst, Left, Middle, Right) :-
|
||||
partition(Compare, Pivot, Lst, [], Left, [], Middle, [], Right).
|
||||
|
||||
:- pred partition(comparison_func(T), T, list(T),
|
||||
list(T), list(T),
|
||||
list(T), list(T),
|
||||
list(T), list(T)).
|
||||
:- mode partition(in, in, in,
|
||||
in, out,
|
||||
in, out,
|
||||
in, out) is det.
|
||||
partition(_, _, [], Left0, Left, Middle0, Middle, Right0, Right) :-
|
||||
Left = Left0,
|
||||
Middle = Middle0,
|
||||
Right = Right0.
|
||||
partition(Compare, Pivot, [Head | Tail], Left0, Left,
|
||||
Middle0, Middle, Right0, Right) :-
|
||||
Compare(Head, Pivot) = Cmp,
|
||||
(if (Cmp = (<))
|
||||
then partition(Compare, Pivot, Tail,
|
||||
[Head | Left0], Left,
|
||||
Middle0, Middle,
|
||||
Right0, Right)
|
||||
else if (Cmp = (=))
|
||||
then partition(Compare, Pivot, Tail,
|
||||
Left0, Left,
|
||||
[Head | Middle0], Middle,
|
||||
Right0, Right)
|
||||
else partition(Compare, Pivot, Tail,
|
||||
Left0, Left,
|
||||
Middle0, Middle,
|
||||
[Head | Right0], Right)).
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%%
|
||||
%%% Quicksort using the first element as pivot.
|
||||
%%%
|
||||
%%% This is not the world's best choice of pivot, but it is the
|
||||
%%% easiest one to get from a linked list.
|
||||
%%%
|
||||
%%% This implementation is *not* tail-recursive--as most quicksort
|
||||
%%% implementations also are not. (However, do an online search on
|
||||
%%% "quicksort fortran 77" and you will find some "tail-recursive"
|
||||
%%% implementations, with the tail recursions expressed as gotos.)
|
||||
%%%
|
||||
|
||||
:- func quicksort(comparison_func(T), list(T)) = list(T).
|
||||
quicksort(_, []) = [].
|
||||
quicksort(Compare, [Pivot | Tail]) = Sorted_Lst :-
|
||||
partition(Compare, Pivot, Tail, Left, Middle, Right),
|
||||
quicksort(Compare, Left) = Sorted_Left,
|
||||
quicksort(Compare, Right) = Sorted_Right,
|
||||
Sorted_Left ++ [Pivot | Middle] ++ Sorted_Right = Sorted_Lst.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
:- func example_numbers = list(int).
|
||||
example_numbers = [1, 3, 9, 5, 8, 6, 5, 1, 7, 9, 8, 6, 4, 2].
|
||||
|
||||
:- func int_compare(int, int) = comparison_result.
|
||||
int_compare(I, J) = Cmp :-
|
||||
if (I < J) then (Cmp = (<))
|
||||
else if (I = J) then (Cmp = (=))
|
||||
else (Cmp = (>)).
|
||||
|
||||
main(!IO) :-
|
||||
quicksort(int_compare, example_numbers) = Sorted_Numbers,
|
||||
print("unsorted: ", !IO),
|
||||
print_line(example_numbers, !IO),
|
||||
print("sorted: ", !IO),
|
||||
print_line(Sorted_Numbers, !IO).
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% local variables:
|
||||
%%% mode: mercury
|
||||
%%% prolog-indent-width: 2
|
||||
%%% end:
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
%%%-------------------------------------------------------------------
|
||||
|
||||
:- module quicksort_task_for_arrays.
|
||||
|
||||
:- interface.
|
||||
:- import_module io.
|
||||
:- pred main(io, io).
|
||||
:- mode main(di, uo) is det.
|
||||
|
||||
:- implementation.
|
||||
:- import_module array.
|
||||
:- import_module int.
|
||||
:- import_module list.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%%
|
||||
%%% Partitioning a subarray into two halves: one with elements less
|
||||
%%% than or equal to a pivot, the other with elements greater than or
|
||||
%%% equal to a pivot.
|
||||
%%%
|
||||
%%% The implementation is tail-recursive.
|
||||
%%%
|
||||
|
||||
:- pred partition(pred(T, T), T, int, int, array(T), array(T), int).
|
||||
:- mode partition(pred(in, in) is semidet, in, in, in,
|
||||
array_di, array_uo, out).
|
||||
partition(Less_than, Pivot, I_first, I_last, Arr0, Arr, I_pivot) :-
|
||||
I = I_first - 1,
|
||||
J = I_last + 1,
|
||||
partition_loop(Less_than, Pivot, I, J, Arr0, Arr, I_pivot).
|
||||
|
||||
:- pred partition_loop(pred(T, T), T, int, int,
|
||||
array(T), array(T), int).
|
||||
:- mode partition_loop(pred(in, in) is semidet, in, in, in,
|
||||
array_di, array_uo, out).
|
||||
partition_loop(Less_than, Pivot, I, J, Arr0, Arr, Pivot_index) :-
|
||||
if (I = J) then (Arr = Arr0,
|
||||
Pivot_index = I)
|
||||
else (I1 = I + 1,
|
||||
I2 = search_right(Less_than, Pivot, I1, J, Arr0),
|
||||
(if (I2 = J) then (Arr = Arr0,
|
||||
Pivot_index = J)
|
||||
else (J1 = J - 1,
|
||||
J2 = search_left(Less_than, Pivot, I2, J1, Arr0),
|
||||
swap(I2, J2, Arr0, Arr1),
|
||||
partition_loop(Less_than, Pivot, I2, J2, Arr1, Arr,
|
||||
Pivot_index)))).
|
||||
|
||||
:- func search_right(pred(T, T), T, int, int, array(T)) = int.
|
||||
:- mode search_right(pred(in, in) is semidet,
|
||||
in, in, in, in) = out is det.
|
||||
search_right(Less_than, Pivot, I, J, Arr0) = K :-
|
||||
if (I = J) then (I = K)
|
||||
else if Less_than(Pivot, Arr0^elem(I)) then (I = K)
|
||||
else (search_right(Less_than, Pivot, I + 1, J, Arr0) = K).
|
||||
|
||||
:- func search_left(pred(T, T), T, int, int, array(T)) = int.
|
||||
:- mode search_left(pred(in, in) is semidet,
|
||||
in, in, in, in) = out is det.
|
||||
search_left(Less_than, Pivot, I, J, Arr0) = K :-
|
||||
if (I = J) then (J = K)
|
||||
else if Less_than(Arr0^elem(J), Pivot) then (J = K)
|
||||
else (search_left(Less_than, Pivot, I, J - 1, Arr0) = K).
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%%
|
||||
%%% Quicksort with median of three as pivot.
|
||||
%%%
|
||||
%%% Like most quicksort implementations, this one is *not*
|
||||
%%% tail-recursive.
|
||||
%%%
|
||||
|
||||
%% quicksort/3 sorts an entire array.
|
||||
:- pred quicksort(pred(T, T), array(T), array(T)).
|
||||
:- mode quicksort(pred(in, in) is semidet, array_di, array_uo) is det.
|
||||
quicksort(Less_than, Arr0, Arr) :-
|
||||
bounds(Arr0, I_first, I_last),
|
||||
quicksort(Less_than, I_first, I_last, Arr0, Arr).
|
||||
|
||||
%% quicksort/5 sorts a subarray.
|
||||
:- pred quicksort(pred(T, T), int, int, array(T), array(T)).
|
||||
:- mode quicksort(pred(in, in) is semidet, in, in,
|
||||
array_di, array_uo) is det.
|
||||
quicksort(Less_than, I_first, I_last, Arr0, Arr) :-
|
||||
if (I_last - I_first >= 2)
|
||||
then (median_of_three(Less_than, I_first, I_last,
|
||||
Arr0, Arr1, Pivot),
|
||||
|
||||
%% Partition only from I_first to I_last - 1.
|
||||
partition(Less_than, Pivot, I_first, I_last - 1,
|
||||
Arr1, Arr2, K),
|
||||
|
||||
%% Now everything that is less than the pivot is to the
|
||||
%% left of K.
|
||||
|
||||
%% Put the pivot at K, moving the element that had been there
|
||||
%% to the end. If K = I_last, then this element is actually
|
||||
%% garbage and will be overwritten with the pivot, which turns
|
||||
%% out to be the greatest element. Otherwise, the moved
|
||||
%% element is not less than the pivot and so the partitioning
|
||||
%% is preserved.
|
||||
Arr2^elem(K) = Elem_to_move,
|
||||
(Arr2^elem(I_last) := Elem_to_move) = Arr3,
|
||||
(Arr3^elem(K) := Pivot) = Arr4,
|
||||
|
||||
%% Sort the subarray on either side of the pivot.
|
||||
quicksort(Less_than, I_first, K - 1, Arr4, Arr5),
|
||||
quicksort(Less_than, K + 1, I_last, Arr5, Arr))
|
||||
|
||||
else if (I_last - I_first = 1) % Two elements.
|
||||
then (Elem_first = Arr0^elem(I_first),
|
||||
Elem_last = Arr0^elem(I_last),
|
||||
(if Less_than(Elem_first, Elem_last)
|
||||
then (Arr = Arr0)
|
||||
else ((Arr0^elem(I_first) := Elem_last) = Arr1,
|
||||
(Arr1^elem(I_last) := Elem_first) = Arr)))
|
||||
|
||||
else (Arr = Arr0). % Zero or one element.
|
||||
|
||||
%% median_of_three/6 both chooses a pivot and rearranges the array
|
||||
%% elements so one may partition them from I_first to I_last - 1,
|
||||
%% leaving the pivot element out of the array.
|
||||
:- pred median_of_three(pred(T, T), int, int, array(T), array(T), T).
|
||||
:- mode median_of_three(pred(in, in) is semidet, in, in,
|
||||
array_di, array_uo, out) is det.
|
||||
median_of_three(Less_than, I_first, I_last, Arr0, Arr, Pivot) :-
|
||||
I_middle = I_first + ((I_last - I_first) // 2),
|
||||
Elem_first = Arr0^elem(I_first),
|
||||
Elem_middle = Arr0^elem(I_middle),
|
||||
Elem_last = Arr0^elem(I_last),
|
||||
(if pred_xor(Less_than, Less_than,
|
||||
Elem_middle, Elem_first,
|
||||
Elem_last, Elem_first)
|
||||
then (Pivot = Elem_first,
|
||||
(if Less_than(Elem_middle, Elem_last)
|
||||
then (Arr1 = (Arr0^elem(I_first) := Elem_middle),
|
||||
Arr = (Arr1^elem(I_middle) := Elem_last))
|
||||
else (Arr = (Arr0^elem(I_first) := Elem_last))))
|
||||
else if pred_xor(Less_than, Less_than,
|
||||
Elem_middle, Elem_first,
|
||||
Elem_middle, Elem_last)
|
||||
then (Pivot = Elem_middle,
|
||||
(if Less_than(Elem_first, Elem_last)
|
||||
then (Arr = (Arr0^elem(I_middle) := Elem_last))
|
||||
else (Arr1 = (Arr0^elem(I_first) := Elem_last),
|
||||
Arr = (Arr1^elem(I_middle) := Elem_first))))
|
||||
else (Pivot = Elem_last,
|
||||
(if Less_than(Elem_first, Elem_middle)
|
||||
then (Arr = Arr0)
|
||||
else (Arr1 = (Arr0^elem(I_first) := Elem_middle),
|
||||
Arr = (Arr1^elem(I_middle) := Elem_first))))).
|
||||
|
||||
:- pred pred_xor(pred(T, T), pred(T, T), T, T, T, T).
|
||||
:- mode pred_xor(pred(in, in) is semidet,
|
||||
pred(in, in) is semidet,
|
||||
in, in, in, in) is semidet.
|
||||
pred_xor(P, Q, W, X, Y, Z) :-
|
||||
if P(W, X) then (not Q(Y, Z)) else Q(Y, Z).
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
:- func example_numbers = list(int).
|
||||
example_numbers = [1, 3, 9, 5, 8, 6, 5, 0, 1, 7, 9, 8, 6, 4, 2, -28,
|
||||
30, 31, 1, 3, 9, 5, 8, 6, 5, 1, 6, 4, 2, -28, 30,
|
||||
-50, 500, -1234, 1234, 12].
|
||||
|
||||
main(!IO) :-
|
||||
(array.from_list(example_numbers, Arr0)),
|
||||
print_line("", !IO),
|
||||
print_line(Arr0, !IO),
|
||||
print_line("", !IO),
|
||||
print_line(" |", !IO),
|
||||
print_line(" V", !IO),
|
||||
print_line("", !IO),
|
||||
quicksort(<, Arr0, Arr1),
|
||||
print_line(Arr1, !IO),
|
||||
print_line("", !IO).
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% local variables:
|
||||
%%% mode: mercury
|
||||
%%% prolog-indent-width: 2
|
||||
%%% end:
|
||||
Loading…
Add table
Add a link
Reference in a new issue