How to resolve the algorithm Sort disjoint sublist step by step in the ATS programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Sort disjoint sublist step by step in the ATS programming language

Table of Contents

Problem Statement

Given a list of values and a set of integer indices into that value list, the task is to sort the values at the given indices, while preserving the values at indices outside the set of those to be sorted. Make your example work with the following list of values and set of indices: Where the correct result would be: In case of one-based indexing, rather than the zero-based indexing above, you would use the indices {7, 2, 8} instead. The indices are described as a set rather than a list but any collection-type of those indices without duplication may be used as long as the example is insensitive to the order of indices given.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Sort disjoint sublist step by step in the ATS programming language

Source code in the ats programming language

#include "share/atspre_staload.hats"
staload UN = "prelude/SATS/unsafe.sats"

(* For simplicity, I implement this task only for sorting values of
   non-linear type. That would include all the basic integer types,
   garbage-collected strings, etc.
   
   Also I freely create arrays as workspace, although the size of any
   workspace array is equal only to the number of indices (not to the
   number of values). *)

extern fn {a : t@ype}
sort_disjoint_sublist$cmp : (a, a) -<> int

fn {a : t@ype}
sort_disjoint_sublist
          {m       : int}
          {n       : int}
          (values  : &list_vt (a, m) >> _,
           indices : list ([i : nat | i < m] int i, n))
    : void =
  let
    typedef index = [i : nat | i < m] int i

    prval () = lemma_list_vt_param values
    prval () = lemma_list_param indices
    val num_values : size_t m = i2sz (list_vt_length values)
    and num_indices : size_t n = i2sz (list_length indices)

    (* Put the indices in ascending order. *)
    val @(pf_ix, pfgc_ix | p_ix) =
      array_ptr_alloc num_indices
    macdef ix = !p_ix
    val () = array_initize_list (ix, sz2i num_indices, indices)
    implement
    array_quicksort$cmp (x, y) =
      if x < y then ~1 else 1
    val () = array_quicksort (ix, num_indices)

    (* Initialize a "refs" array with pointers to the relevant list
       nodes. The pointers will be in ascending index order. *)
    val @(pf_refs, pfgc_refs | p_refs) =
      array_ptr_alloc num_indices
    fun
    init_refs {j      : nat | j <= m}
              {i      : nat | i <= n}
              {p_refs : addr}
              ..
              (pf_refs : !array_v (ptr?, p_refs + (i * sizeof ptr),
                                   n - i)
                          >> array_v (ptr, p_refs + (i * sizeof ptr),
                                      n - i) |
               ix      : &array (index, n),
               p_refs  : ptr p_refs,
               i       : size_t i,
               values  : &list_vt (a, m - j),
               j       : size_t j)
        : void =
      if i < num_indices then
        case+ values of
        | list_vt_nil () => $effmask_exn assertloc (false)
        | @ list_vt_cons (head, tail) =>
          if j = ix[i] then
            let
              prval @(pf_elem, pf_rest) = array_v_uncons pf_refs
              val p = ptr_add (p_refs, i)
              val () = ptr_set (pf_elem | p, addr@ values)
              val () = init_refs (pf_rest | ix, p_refs, succ i,
                                            tail, succ j)
              prval () = pf_refs := array_v_cons (pf_elem, pf_rest)
              prval () = fold@ values
            in
            end
          else
            let
              val () = init_refs (pf_refs | ix, p_refs, i,
                                            tail, succ j)
              prval () = fold@ values
            in
            end
      else
        let
          prval () = pf_refs := array_v_unnil_nil{ptr?, ptr} pf_refs
        in
        end
    val () = init_refs (pf_refs | ix, p_refs, i2sz 0, values, i2sz 0)

    (* Sort through the "refs" pointers. Here we will do that by
       copying the values to an array, sorting the array, then writing
       the sorted values back. One could also do the sort in place,
       however. *)
    val @(pf_vals, pfgc_vals | p_vals) =
      array_ptr_alloc num_indices
    macdef vals = !p_vals
    implement
    array_initize$init (i, x) =
      let
        val @(pf1, fpf1 | p1) = $UN.ptr_vtake{array (ptr, n)} p_refs
        macdef refs = !p1
        val i1 = g1ofg0 i
        prval () = lemma_g1uint_param i1
        val () = assertloc (i1 < num_indices)
        val @(pf2, fpf2 | p2) = $UN.ptr_vtake{List1_vt a} (refs[i1])
        val+ @ list_vt_cons (head, tail) = !p2
        val () = x := head
        prval () = fold@ (!p2)
        prval () = fpf2 pf2
        prval () = fpf1 pf1
      in
      end
    val () = array_initize (vals, num_indices)
    implement
    array_quicksort$cmp (x, y) =
      sort_disjoint_sublist$cmp (x, y)
    val () = array_quicksort (vals, num_indices)
    fun
    write_back_values
              {i       : nat | i <= n}
              {p_refs  : addr}
              (pf_refs : !array_v (ptr, p_refs, n) |
               p_refs  : ptr p_refs,
               vals    : &array (a, n),
               i       : size_t i)
        : void =
      if i <> num_indices then
        let
          macdef refs = !p_refs
          val @(pf1, fpf1 | p1) = $UN.ptr_vtake{List1_vt a} (refs[i])
          val+ @ list_vt_cons (head, tail) = !p1
          val () = head := vals[i]
          prval () = fold@ (!p1)
          prval () = fpf1 pf1
        in
          write_back_values (pf_refs | p_refs, vals, succ i)
        end
    val () = write_back_values (pf_refs | p_refs, vals, i2sz 0)
  in
    array_ptr_free (pf_ix, pfgc_ix | p_ix);
    array_ptr_free (pf_refs, pfgc_refs | p_refs);
    array_ptr_free (pf_vals, pfgc_vals | p_vals)
  end

implement
sort_disjoint_sublist$cmp (x, y) =
  if x < y then
    ~1
  else if y < x then
    1
  else
    0

implement
main0 () =
  let
    var values = $list_vt{int} (7, 6, 5, 4, 3, 2, 1, 0)
    val indices = $list{[i : nat | i < 8] int i} (6, 1, 7)
  in
    println! values;
    sort_disjoint_sublist (values, indices);
    println! values;
    free values
  end

  

You may also check:
How to resolve the algorithm Sieve of Eratosthenes step by step in the ooRexx programming language
You may also check:How to resolve the algorithm Langton's ant step by step in the Euphoria programming language
You may also check:How to resolve the algorithm Damm algorithm step by step in the C# programming language
You may also check:How to resolve the algorithm Loops/Break step by step in the PicoLisp programming language
You may also check:How to resolve the algorithm Multiple regression step by step in the Perl programming language