Sorting algorithms/Patience sort: Difference between revisions
Content added Content deleted
Line 1,124: | Line 1,124: | ||
=={{header|ATS}}== |
=={{header|ATS}}== |
||
===A patience sort for arrays of non-linear elements=== |
|||
{{trans|Fortran}} |
|||
The sort routine returns an array of indices into the original array, which is left unmodified. |
|||
<lang ats>(*------------------------------------------------------------------*) |
|||
#include "share/atspre_staload.hats" |
|||
vtypedef array_tup_vt (a : vt@ype+, p : addr, n : int) = |
|||
(* An array, without size information attached. *) |
|||
@(array_v (a, p, n), |
|||
mfree_gc_v p | |
|||
ptr p) |
|||
extern fn {a : t@ype} |
|||
patience_sort |
|||
{ifirst, len : int | 0 <= ifirst} |
|||
{n : int | ifirst + len <= n} |
|||
(arr : &RD(array (a, n)), |
|||
ifirst : size_t ifirst, |
|||
len : size_t len) |
|||
:<!wrt> (* Return an array of indices into arr. *) |
|||
[p : addr] |
|||
array_tup_vt |
|||
([i : int | len == 0 || |
|||
(ifirst <= i && i < ifirst + len)] size_t i, |
|||
p, len) |
|||
(* patience_sort$lt : the order predicate. *) |
|||
extern fn {a : t@ype} |
|||
patience_sort$lt (x : a, y : a) :<> bool |
|||
(*------------------------------------------------------------------*) |
|||
(* |
|||
In the following implementation of next_power_of_two: |
|||
* I implement it as a template for all types of kind g1uint. This |
|||
includes dependent forms of uint, usint, ulint, ullint, size_t, |
|||
and yet more types in the prelude; also whatever others one may |
|||
create. |
|||
* I prove the result is not less than the input. |
|||
* I prove the result is less than twice the input. |
|||
* I prove the result is a power of two. This last proof is |
|||
provided in the form of an EXP2 prop. |
|||
* I do NOT return what number two is raised to (though I easily |
|||
could have). I leave that number "existentially defined". That |
|||
is, I prove only that some such non-negative number exists. |
|||
*) |
|||
fn {tk : tkind} |
|||
next_power_of_two |
|||
{i : pos} |
|||
(i : g1uint (tk, i)) |
|||
:<> [k : int | i <= k; k < 2 * i] |
|||
[n : nat] |
|||
@(EXP2 (n, k) | g1uint (tk, k)) = |
|||
let |
|||
(* This need not be a fast implementation. *) |
|||
val one : g1uint (tk, 1) = g1u2u 1u |
|||
fun |
|||
loop {j : pos | j < i} .<i + i - j>. |
|||
(pf : [n : nat] EXP2 (n, j) | |
|||
j : g1uint (tk, j)) |
|||
:<> [k : int | i <= k; k < 2 * i] |
|||
[n : nat] |
|||
@(EXP2 (n, k) | g1uint (tk, k)) = |
|||
let |
|||
val j2 = j + j |
|||
in |
|||
if i <= j2 then |
|||
@(EXP2ind pf | j2) |
|||
else |
|||
loop (EXP2ind pf | j2) |
|||
end |
|||
in |
|||
if i = one then |
|||
@(EXP2bas () | one) |
|||
else |
|||
loop (EXP2bas () | one) |
|||
end |
|||
(*------------------------------------------------------------------*) |
|||
stadef link (ifirst : int, ilast : int, i : int) : bool = |
|||
0 <= i && i <= ilast - ifirst + 1 |
|||
typedef link_t (ifirst : int, ilast : int, i : int) = |
|||
(* A size_t within legal range for a normalized link, including the |
|||
"nil" link 0. *) |
|||
[link (ifirst, ilast, i)] |
|||
size_t i |
|||
typedef link_t (ifirst : int, ilast : int) = |
|||
[i : int] |
|||
link_t (ifirst, ilast, i) |
|||
fn {a : t@ype} |
|||
find_pile {ifirst, ilast : int | ifirst <= ilast} |
|||
{n : int | ilast < n} |
|||
{num_piles : nat | num_piles <= ilast - ifirst + 1} |
|||
{n_piles : int | ilast - ifirst + 1 <= n_piles} |
|||
{q : pos | q <= ilast - ifirst + 1} |
|||
(ifirst : size_t ifirst, |
|||
arr : &RD(array (a, n)), |
|||
num_piles : size_t num_piles, |
|||
piles : &RD(array (link_t (ifirst, ilast), |
|||
n_piles)), |
|||
q : size_t q) |
|||
:<> [i : pos | i <= num_piles + 1] |
|||
size_t i = |
|||
(* |
|||
Bottenbruch search for the leftmost pile whose top is greater than |
|||
or equal to the next value dealt by "deal". |
|||
References: |
|||
* H. Bottenbruch, "Structure and use of ALGOL 60", Journal of |
|||
the ACM, Volume 9, Issue 2, April 1962, pp.161-221. |
|||
https://doi.org/10.1145/321119.321120 |
|||
The general algorithm is described on pages 214 and 215. |
|||
* https://en.wikipedia.org/w/index.php?title=Binary_search_algorithm&oldid=1062988272#Alternative_procedure |
|||
*) |
|||
if num_piles = i2sz 0 then |
|||
i2sz 1 |
|||
else |
|||
let |
|||
macdef lt = patience_sort$lt<a> |
|||
prval () = lemma_g1uint_param ifirst |
|||
prval () = prop_verify {0 <= ifirst} () |
|||
fun |
|||
loop {j, k : nat | j <= k; k < num_piles} |
|||
.<k - j>. |
|||
(arr : &RD(array (a, n)), |
|||
piles : &array (link_t (ifirst, ilast), n_piles), |
|||
j : size_t j, |
|||
k : size_t k) |
|||
:<> [i : pos | i <= num_piles + 1] |
|||
size_t i = |
|||
if j = k then |
|||
begin |
|||
if succ j <> num_piles then |
|||
succ j |
|||
else |
|||
let |
|||
val piles_j = piles[j] |
|||
val () = $effmask_exn assertloc (piles_j <> g1u2u 0u) |
|||
val x1 = arr[pred q + ifirst] |
|||
and x2 = arr[pred piles_j + ifirst] |
|||
in |
|||
if x2 \lt x1 then |
|||
succ (succ j) |
|||
else |
|||
succ j |
|||
end |
|||
end |
|||
else |
|||
let |
|||
typedef index (i : int) = [0 <= i; i < n] size_t i |
|||
typedef index = [i : int] index i |
|||
stadef i = j + ((k - j) / 2) |
|||
val i : size_t i = j + ((k - j) / g1u2u 2u) |
|||
val piles_j = piles[j] |
|||
val () = $effmask_exn assertloc (piles_j <> g1u2u 0u) |
|||
val x1 = arr[pred q + ifirst] |
|||
and x2 = arr[pred piles_j + ifirst] |
|||
in |
|||
if x2 \lt x1 then |
|||
loop (arr, piles, i + 1, k) |
|||
else |
|||
loop (arr, piles, j, i) |
|||
end |
|||
in |
|||
loop (arr, piles, g1u2u 0u, pred num_piles) |
|||
end |
|||
fn {a : t@ype} |
|||
deal {ifirst, ilast : int | ifirst <= ilast} |
|||
{n : int | ilast < n} |
|||
(ifirst : size_t ifirst, |
|||
ilast : size_t ilast, |
|||
arr : &RD(array (a, n))) |
|||
:<!wrt> [num_piles : int | num_piles <= ilast - ifirst + 1] |
|||
[n_piles : int | ilast - ifirst + 1 <= n_piles] |
|||
[n_links : int | ilast - ifirst + 1 <= n_links] |
|||
[p_piles : addr] |
|||
[p_links : addr] |
|||
@(size_t num_piles, |
|||
array_tup_vt (link_t (ifirst, ilast), |
|||
p_piles, n_piles), |
|||
array_tup_vt (link_t (ifirst, ilast), |
|||
p_links, n_links)) = |
|||
let |
|||
prval () = prop_verify {0 < ilast - ifirst + 1} () |
|||
stadef num_elems = ilast - ifirst + 1 |
|||
val num_elems : size_t num_elems = succ (ilast - ifirst) |
|||
typedef link_t (i : int) = link_t (ifirst, ilast, i) |
|||
typedef link_t = link_t (ifirst, ilast) |
|||
val zero : size_t 0 = g1u2u 0u |
|||
val one : size_t 1 = g1u2u 1u |
|||
val link_nil : link_t 0 = g1u2u 0u |
|||
fun |
|||
loop {q : pos | q <= num_elems + 1} |
|||
{m : nat | m <= num_elems} |
|||
.<num_elems + 1 - q>. |
|||
(arr : &RD(array (a, n)), |
|||
q : size_t q, |
|||
piles : &array (link_t, num_elems), |
|||
links : &array (link_t, num_elems), |
|||
m : size_t m) |
|||
:<!wrt> [num_piles : nat | num_piles <= num_elems] |
|||
size_t num_piles = |
|||
if q = succ (num_elems) then |
|||
m |
|||
else |
|||
let |
|||
val i = find_pile {ifirst, ilast} (ifirst, arr, m, piles, q) |
|||
(* We have no proof the number of elements will not exceed |
|||
storage. However, we know it will not, because the number |
|||
of piles cannot exceed the size of the input. Let us get |
|||
a "proof" by runtime check. *) |
|||
val () = $effmask_exn assertloc (i <= num_elems) |
|||
in |
|||
links[pred q] := piles[pred i]; |
|||
piles[pred i] := q; |
|||
if i = succ m then |
|||
loop {q + 1} (arr, succ q, piles, links, succ m) |
|||
else |
|||
loop {q + 1} (arr, succ q, piles, links, m) |
|||
end |
|||
val piles_tup = array_ptr_alloc<link_t> num_elems |
|||
macdef piles = !(piles_tup.2) |
|||
val () = array_initize_elt<link_t> (piles, num_elems, link_nil) |
|||
val links_tup = array_ptr_alloc<link_t> num_elems |
|||
macdef links = !(links_tup.2) |
|||
val () = array_initize_elt<link_t> (links, num_elems, link_nil) |
|||
val num_piles = loop (arr, one, piles, links, zero) |
|||
in |
|||
@(num_piles, piles_tup, links_tup) |
|||
end |
|||
fn {a : t@ype} |
|||
k_way_merge {ifirst, ilast : int | ifirst <= ilast} |
|||
{n : int | ilast < n} |
|||
{n_piles : int | ilast - ifirst + 1 <= n_piles} |
|||
{num_piles : pos | num_piles <= ilast - ifirst + 1} |
|||
{n_links : int | ilast - ifirst + 1 <= n_links} |
|||
(ifirst : size_t ifirst, |
|||
ilast : size_t ilast, |
|||
arr : &RD(array (a, n)), |
|||
num_piles : size_t num_piles, |
|||
piles : &array (link_t (ifirst, ilast), n_piles), |
|||
links : &array (link_t (ifirst, ilast), n_links)) |
|||
:<!wrt> (* Return an array of indices into arr. *) |
|||
[p : addr] |
|||
array_tup_vt |
|||
([i : int | ifirst <= i; i <= ilast] size_t i, |
|||
p, ilast - ifirst + 1) = |
|||
(* |
|||
k-way merge by tournament tree. |
|||
See Knuth, volume 3, and also |
|||
https://en.wikipedia.org/w/index.php?title=K-way_merge_algorithm&oldid=1047851465#Tournament_Tree |
|||
However, I store a winners tree instead of the recommended losers |
|||
tree. If the tree were stored as linked nodes, it would probably |
|||
be more efficient to store a losers tree. However, I am storing |
|||
the tree as an array, and one can find an opponent quickly by |
|||
simply toggling the least significant bit of a competitor's array |
|||
index. |
|||
*) |
|||
let |
|||
typedef link_t (i : int) = link_t (ifirst, ilast, i) |
|||
typedef link_t = [i : int] link_t i |
|||
val link_nil : link_t 0 = g1u2u 0u |
|||
typedef index_t (i : int) = [ifirst <= i; i <= ilast] size_t i |
|||
typedef index_t = [i : int] index_t i |
|||
val [total_external_nodes : int] |
|||
@(_ | total_external_nodes) = next_power_of_two num_piles |
|||
prval () = prop_verify {num_piles <= total_external_nodes} () |
|||
stadef total_nodes = (2 * total_external_nodes) - 1 |
|||
val total_nodes : size_t total_nodes = |
|||
pred (g1u2u 2u * total_external_nodes) |
|||
(* We will ignore index 0 of the winners tree arrays. *) |
|||
stadef winners_size = total_nodes + 1 |
|||
val winners_size : size_t winners_size = succ total_nodes |
|||
val winners_values_tup = array_ptr_alloc<link_t> winners_size |
|||
macdef winners_values = !(winners_values_tup.2) |
|||
val () = array_initize_elt<link_t> (winners_values, winners_size, |
|||
link_nil) |
|||
val winners_links_tup = array_ptr_alloc<link_t> winners_size |
|||
macdef winners_links = !(winners_links_tup.2) |
|||
val () = array_initize_elt<link_t> (winners_links, winners_size, |
|||
link_nil) |
|||
(* - - - - - - - - - - - - - - - - - - - - - - - - - - *) |
|||
(* Record which pile a winner will have come from. *) |
|||
fun |
|||
init_pile_links |
|||
{i : nat | i <= num_piles} |
|||
.<num_piles - i>. |
|||
(winners_links : &array (link_t, winners_size), |
|||
i : size_t i) |
|||
:<!wrt> void = |
|||
if i <> num_piles then |
|||
begin |
|||
winners_links[total_external_nodes + i] := succ i; |
|||
init_pile_links (winners_links, succ i) |
|||
end |
|||
val () = init_pile_links (winners_links, g1u2u 0u) |
|||
(* - - - - - - - - - - - - - - - - - - - - - - - - - - *) |
|||
(* The top of each pile becomes a starting competitor. *) |
|||
fun |
|||
init_competitors |
|||
{i : nat | i <= num_piles} |
|||
.<num_piles - i>. |
|||
(winners_values : &array (link_t, winners_size), |
|||
piles : &array (link_t, n_piles), |
|||
i : size_t i) |
|||
:<!wrt> void = |
|||
if i <> num_piles then |
|||
begin |
|||
winners_values[total_external_nodes + i] := piles[i]; |
|||
init_competitors (winners_values, piles, succ i) |
|||
end |
|||
val () = init_competitors (winners_values, piles, g1u2u 0u) |
|||
(* - - - - - - - - - - - - - - - - - - - - - - - - - - *) |
|||
(* Discard the top of each pile. *) |
|||
fun |
|||
discard_tops {i : nat | i <= num_piles} |
|||
.<num_piles - i>. |
|||
(piles : &array (link_t, n_piles), |
|||
links : &array (link_t, n_links), |
|||
i : size_t i) |
|||
:<!wrt> void = |
|||
if i <> num_piles then |
|||
let |
|||
val link = piles[i] |
|||
(* None of the piles should have been empty. *) |
|||
val () = $effmask_exn assertloc (link <> g1u2u 0u) |
|||
in |
|||
piles[i] := links[pred link]; |
|||
discard_tops (piles, links, succ i) |
|||
end |
|||
val () = discard_tops (piles, links, g1u2u 0u) |
|||
(* - - - - - - - - - - - - - - - - - - - - - - - - - - *) |
|||
(* How to play a game. *) |
|||
fn |
|||
play_game {i : int | 2 <= i; i <= total_nodes} |
|||
(arr : &RD(array (a, n)), |
|||
winners_values : &array (link_t, winners_size), |
|||
i : size_t i) |
|||
:<> [iwinner : pos | iwinner <= total_nodes] |
|||
size_t iwinner = |
|||
let |
|||
macdef lt = patience_sort$lt<a> |
|||
fn |
|||
find_opponent {i : int | 2 <= i; i <= total_nodes} |
|||
(i : size_t i) |
|||
:<> [j : int | 2 <= j; j <= total_nodes] |
|||
size_t j = |
|||
let |
|||
(* The prelude contains bitwise operations only for |
|||
non-dependent unsigned integer. We will not bother to |
|||
add them ourselves, but instead go back and forth |
|||
between dependent and non-dependent. *) |
|||
val i0 = g0ofg1 i |
|||
val j0 = g0uint_lxor<size_kind> (i0, g0u2u 1u) |
|||
val j = g1ofg0 j0 |
|||
(* We have no proof the opponent is in the proper |
|||
range. Create a "proof" by runtime checks. *) |
|||
val () = $effmask_exn assertloc (g1u2u 2u <= j) |
|||
val () = $effmask_exn assertloc (j <= total_nodes) |
|||
in |
|||
j |
|||
end |
|||
val j = find_opponent i |
|||
val winner_i = winners_values[i] |
|||
and winner_j = winners_values[j] |
|||
in |
|||
if winner_i = link_nil then |
|||
j |
|||
else if winner_j = link_nil then |
|||
i |
|||
else |
|||
let |
|||
val i1 = pred winner_i + ifirst |
|||
and i2 = pred winner_j + ifirst |
|||
prval () = lemma_g1uint_param i1 |
|||
prval () = lemma_g1uint_param i2 |
|||
in |
|||
if arr[i2] \lt arr[i1] then j else i |
|||
end |
|||
end |
|||
(* - - - - - - - - - - - - - - - - - - - - - - - - - - *) |
|||
fun |
|||
build_tree {istart : pos | istart <= total_external_nodes} |
|||
.<istart>. |
|||
(arr : &RD(array (a, n)), |
|||
winners_values : &array (link_t, winners_size), |
|||
winners_links : &array (link_t, winners_size), |
|||
istart : size_t istart) |
|||
:<!wrt> void = |
|||
if istart <> 1 then |
|||
let |
|||
fun |
|||
play_initial_games |
|||
{i : int | istart <= i; i <= (2 * istart) + 1} |
|||
.<(2 * istart) + 1 - i>. |
|||
(arr : &RD(array (a, n)), |
|||
winners_values : &array (link_t, winners_size), |
|||
winners_links : &array (link_t, winners_size), |
|||
i : size_t i) |
|||
:<!wrt> void = |
|||
if i <= pred (istart + istart) then |
|||
let |
|||
val iwinner = play_game (arr, winners_values, i) |
|||
and i2 = i / g1u2u 2u |
|||
in |
|||
winners_values[i2] := winners_values[iwinner]; |
|||
winners_links[i2] := winners_links[iwinner]; |
|||
play_initial_games (arr, winners_values, |
|||
winners_links, succ (succ i)) |
|||
end |
|||
in |
|||
play_initial_games (arr, winners_values, winners_links, |
|||
istart); |
|||
build_tree (arr, winners_values, winners_links, |
|||
istart / g1u2u 2u) |
|||
end |
|||
val () = build_tree (arr, winners_values, winners_links, |
|||
total_external_nodes) |
|||
(* - - - - - - - - - - - - - - - - - - - - - - - - - - *) |
|||
fun |
|||
replay_games {i : pos | i <= total_nodes} |
|||
.<i>. |
|||
(arr : &RD(array (a, n)), |
|||
winners_values : &array (link_t, winners_size), |
|||
winners_links : &array (link_t, winners_size), |
|||
i : size_t i) |
|||
:<!wrt> void = |
|||
if i <> g1u2u 1u then |
|||
let |
|||
val iwinner = play_game (arr, winners_values, i) |
|||
and i2 = i / g1u2u 2u |
|||
in |
|||
winners_values[i2] := winners_values[iwinner]; |
|||
winners_links[i2] := winners_links[iwinner]; |
|||
replay_games (arr, winners_values, winners_links, i2) |
|||
end |
|||
stadef num_elems = ilast - ifirst + 1 |
|||
val num_elems : size_t num_elems = succ (ilast - ifirst) |
|||
val sorted_tup = array_ptr_alloc<index_t> num_elems |
|||
fun |
|||
merge {isorted : nat | isorted <= num_elems} |
|||
{p_sorted : addr} |
|||
.<num_elems - isorted>. |
|||
(pf_sorted : !array_v (index_t?, p_sorted, |
|||
num_elems - isorted) |
|||
>> array_v (index_t, p_sorted, |
|||
num_elems - isorted) | |
|||
arr : &RD(array (a, n)), |
|||
piles : &array (link_t, n_piles), |
|||
links : &array (link_t, n_links), |
|||
winners_values : &array (link_t, winners_size), |
|||
winners_links : &array (link_t, winners_size), |
|||
p_sorted : ptr p_sorted, |
|||
isorted : size_t isorted) |
|||
:<!wrt> void = |
|||
(* This function not only fills in the "sorted_tup" array, but |
|||
transforms it from "uninitialized" to "initialized". *) |
|||
if isorted <> num_elems then |
|||
let |
|||
prval @(pf_elem, pf_rest) = array_v_uncons pf_sorted |
|||
val winner = winners_values[1] |
|||
val () = $effmask_exn assertloc (winner <> link_nil) |
|||
val () = !p_sorted := pred winner + ifirst |
|||
(* Move to the next element in the winner's pile. *) |
|||
val ilink = winners_links[1] |
|||
val () = $effmask_exn assertloc (ilink <> link_nil) |
|||
val inext = piles[pred ilink] |
|||
val () = (if inext <> link_nil then |
|||
piles[pred ilink] := links[pred inext]) |
|||
(* Replay games, with the new element as a competitor. *) |
|||
val i = (total_nodes / g1u2u 2u) + ilink |
|||
val () = $effmask_exn assertloc (i <= total_nodes) |
|||
val () = winners_values[i] := inext |
|||
val () = |
|||
replay_games (arr, winners_values, winners_links, i) |
|||
val () = merge (pf_rest | arr, piles, links, |
|||
winners_values, winners_links, |
|||
ptr_succ<index_t> p_sorted, |
|||
succ isorted) |
|||
prval () = pf_sorted := array_v_cons (pf_elem, pf_rest) |
|||
in |
|||
end |
|||
else |
|||
let |
|||
prval () = pf_sorted := |
|||
array_v_unnil_nil{index_t?, index_t} pf_sorted |
|||
in |
|||
end |
|||
val () = merge (sorted_tup.0 | arr, piles, links, |
|||
winners_values, winners_links, |
|||
sorted_tup.2, i2sz 0) |
|||
val () = array_ptr_free (winners_values_tup.0, |
|||
winners_values_tup.1 | |
|||
winners_values_tup.2) |
|||
val () = array_ptr_free (winners_links_tup.0, |
|||
winners_links_tup.1 | |
|||
winners_links_tup.2) |
|||
in |
|||
sorted_tup |
|||
end |
|||
implement {a} |
|||
patience_sort (arr, ifirst, len) = |
|||
let |
|||
prval () = lemma_g1uint_param ifirst |
|||
prval () = lemma_g1uint_param len |
|||
in |
|||
if len = i2sz 0 then |
|||
let |
|||
val sorted_tup = array_ptr_alloc<size_t 0> len |
|||
prval () = sorted_tup.0 := |
|||
array_v_unnil_nil{Size_t?, Size_t} sorted_tup.0 |
|||
in |
|||
sorted_tup |
|||
end |
|||
else |
|||
let |
|||
val ilast = ifirst + pred len |
|||
val @(num_piles, piles_tup, links_tup) = |
|||
deal<a> (ifirst, ilast, arr) |
|||
macdef piles = !(piles_tup.2) |
|||
macdef links = !(links_tup.2) |
|||
prval () = lemma_g1uint_param num_piles |
|||
val () = $effmask_exn assertloc (num_piles <> i2sz 0) |
|||
val sorted_tup = k_way_merge<a> (ifirst, ilast, arr, |
|||
num_piles, piles, links) |
|||
in |
|||
array_ptr_free (piles_tup.0, piles_tup.1 | piles_tup.2); |
|||
array_ptr_free (links_tup.0, links_tup.1 | links_tup.2); |
|||
sorted_tup |
|||
end |
|||
end |
|||
(*------------------------------------------------------------------*) |
|||
fn |
|||
int_patience_sort_ascending |
|||
{ifirst, len : int | 0 <= ifirst} |
|||
{n : int | ifirst + len <= n} |
|||
(arr : &RD(array (int, n)), |
|||
ifirst : size_t ifirst, |
|||
len : size_t len) |
|||
:<!wrt> [p : addr] |
|||
array_tup_vt |
|||
([i : int | len == 0 || |
|||
(ifirst <= i && i < ifirst + len)] size_t i, |
|||
p, len) = |
|||
let |
|||
implement |
|||
patience_sort$lt<int> (x, y) = |
|||
x < y |
|||
in |
|||
patience_sort<int> (arr, ifirst, len) |
|||
end |
|||
fn {a : t@ype} |
|||
find_length {n : int} |
|||
(lst : list (a, n)) |
|||
:<> [m : int | m == n] size_t m = |
|||
let |
|||
prval () = lemma_list_param lst |
|||
in |
|||
g1i2u (length lst) |
|||
end |
|||
implement |
|||
main0 () = |
|||
let |
|||
val example_list = |
|||
$list (22, 15, 98, 82, 22, 4, 58, 70, 80, 38, 49, 48, 46, 54, |
|||
93, 8, 54, 2, 72, 84, 86, 76, 53, 37, 90) |
|||
val ifirst = i2sz 10 |
|||
val [len : int] len = find_length example_list |
|||
#define ARRSZ 100 |
|||
val () = assertloc (i2sz 10 + len <= ARRSZ) |
|||
var arr : array (int, ARRSZ) |
|||
val () = array_initize_elt<int> (arr, i2sz ARRSZ, 0) |
|||
prval @(pf_left, pf_right) = |
|||
array_v_split {int} {..} {ARRSZ} {10} (view@ arr) |
|||
prval @(pf_middle, pf_right) = |
|||
array_v_split {int} {..} {90} {len} pf_right |
|||
val p = ptr_add<int> (addr@ arr, 10) |
|||
val () = array_copy_from_list<int> (!p, example_list) |
|||
prval pf_right = array_v_unsplit (pf_middle, pf_right) |
|||
prval () = view@ arr := array_v_unsplit (pf_left, pf_right) |
|||
val @(pf_sorted, pfgc_sorted | p_sorted) = |
|||
int_patience_sort_ascending (arr, i2sz 10, len) |
|||
macdef sorted = !p_sorted |
|||
var i : [i : nat | i <= len] size_t i |
|||
in |
|||
print! ("unsorted "); |
|||
for (i := i2sz 0; i <> len; i := succ i) |
|||
print! (" ", arr[i2sz 10 + i]); |
|||
println! (); |
|||
print! ("sorted "); |
|||
for (i := i2sz 0; i <> len; i := succ i) |
|||
print! (" ", arr[sorted[i]]); |
|||
println! (); |
|||
array_ptr_free (pf_sorted, pfgc_sorted | p_sorted) |
|||
end |
|||
(*------------------------------------------------------------------*)</lang> |
|||
{{out}} |
|||
<pre>$ patscc -O3 -DATS_MEMALLOC_LIBC patience_sort_task.dats && ./a.out |
|||
unsorted 22 15 98 82 22 4 58 70 80 38 49 48 46 54 93 8 54 2 72 84 86 76 53 37 90 |
|||
sorted 2 4 8 15 22 22 37 38 46 48 49 53 54 54 58 70 72 76 80 82 84 86 90 93 98</pre> |
|||
===A patience sort for non-linear lists of integers, guaranteeing a sorted result=== |
===A patience sort for non-linear lists of integers, guaranteeing a sorted result=== |