namespace RosettaCode {
  using System;

  public class MergeSort<T> where T : IComparable {
    #region Constants
    public const UInt32 INSERTION_LIMIT_DEFAULT = 12;
    public const Int32 MERGES_DEFAULT = 6;
    #endregion

    #region Properties
    public UInt32 InsertionLimit { get; }
    protected UInt32[] Positions { get; set; }

    private Int32 merges;
    public Int32 Merges {
      get { return merges; }
      set {
        // A minimum of 2 merges are required
        if (value > 1)
          merges = value;
        else
          throw new ArgumentOutOfRangeException($"value = {value} must be greater than one", nameof(Merges));

        if (Positions == null || Positions.Length != merges)
          Positions = new UInt32[merges];
      }
    }
    #endregion

    #region Constructors
    public MergeSort(UInt32 insertionLimit, Int32 merges) {
      InsertionLimit = insertionLimit;
      Merges = merges;
    }

    public MergeSort()
      : this(INSERTION_LIMIT_DEFAULT, MERGES_DEFAULT) {
    }
    #endregion

    #region Sort Methods
    public void Sort(T[] entries) {
      // Allocate merge buffer
      var entries2 = new T[entries.Length];
      Sort(entries, entries2, 0, entries.Length - 1);
    }

    // Top-Down K-way Merge Sort
    public void Sort(T[] entries1, T[] entries2, Int32 first, Int32 last) {
      var length = last + 1 - first;
      if (length < 2) return;
      if (length < Merges || length < InsertionLimit) {
        InsertionSort<T>.Sort(entries1, first, last);
        return;
      }

      var left = first;
      var size = ceiling(length, Merges);
      for (var remaining = length; remaining > 0; remaining -= size, left += size) {
        var right = left + Math.Min(remaining, size) - 1;
        Sort(entries1, entries2, left, right);
      }

      Merge(entries1, entries2, first, last);
      Array.Copy(entries2, first, entries1, first, length);
    }
    #endregion

    #region Merge Methods
    public void Merge(T[] entries1, T[] entries2, Int32 first, Int32 last) {
      Array.Clear(Positions, 0, Merges);
      // This implementation has a quadratic time dependency on the number of merges
      for (var index = first; index <= last; index++)
        entries2[index] = remove(entries1, first, last);
    }

    private T remove(T[] entries, Int32 first, Int32 last) {
      T entry = default;
      Int32? found = default;
      var length = last + 1 - first;

      var index = 0;
      var left = first;
      var size = ceiling(length, Merges);
      for (var remaining = length; remaining > 0; remaining -= size, left += size, index++) {
        var position = Positions[index];
        if (position < Math.Min(remaining, size)) {
          var next = entries[left + position];
          if (!found.HasValue || entry.CompareTo(next) > 0) {
            found = index;
            entry = next;
          }
        }
      }

      // Remove entry
      Positions[found.Value]++;
      return entry;
    }
    #endregion

    #region Math Methods
    private static Int32 ceiling(Int32 numerator, Int32 denominator) {
      return (numerator + denominator - 1) / denominator;
    }
    #endregion
  }

  #region Insertion Sort
  static class InsertionSort<T> where T : IComparable {
    public static void Sort(T[] entries, Int32 first, Int32 last) {
      for (var next = first + 1; next <= last; next++)
        insert(entries, first, next);
    }

    /// <summary>Bubble next entry up to its sorted location, assuming entries[first:next - 1] are already sorted.</summary>
    private static void insert(T[] entries, Int32 first, Int32 next) {
      var entry = entries[next];
      while (next > first && entries[next - 1].CompareTo(entry) > 0)
        entries[next] = entries[--next];
      entries[next] = entry;
    }
  }
  #endregion
}


class Array {
    method insertion_sort {
        { |i|
            var j = i-1
            var k = self[i]
            while ((j >= 0) && (k < self[j])) {
                self[j+1] = self[j]
                j--
            }
            self[j+1] = k
        } << 1..self.end
        return self
    }
}

var a = 10.of { 100.irand }
say a.insertion_sort


* read data into an array
	A = table()
	i = 0
readln	A<i = i + 1> = trim(input)	:s(readln)
	aSize = i - 1

* sort array
	i = 1
loop1	value = A<i>
	j = i - 1
loop2	gt(j,0) gt(A<j>,value)	:f(done2)
	A<j + 1> = A<j>
	j = j - 1	:(loop2)
done2	A<j + 1> = value
	i = ?lt(i,aSize) i + 1	:s(loop1)
	i = 1

* output sorted data
while	output = A<i>; i = ?lt(i,aSize) i + 1	:s(while)
end


quickSort(v)={
  if(#v<2, return(v));
  my(less=List(),more=List(),same=List(),pivot);
  pivot=median([v[random(#v)+1],v[random(#v)+1],v[random(#v)+1]]); \\ Middle-of-three
  for(i=1,#v,
    if(v[i]<pivot,
      listput(less, v[i]),
      if(v[i]==pivot, listput(same, v[i]), listput(more, v[i]))
    )
  );
  concat(quickSort(Vec(less)), concat(Vec(same), quickSort(Vec(more))))
};
median(v)={
  vecsort(v)[#v>>1]
};


Procedure GnomeSort(Array a(1))
  Protected Size = ArraySize(a()) + 1
  Protected i = 1, j = 2

  While i < Size
    If a(i - 1) <= a(i)
      ;for descending SORT, use >= for comparison
      i = j
      j + 1
    Else
      Swap a(i - 1), a(i)
      i - 1
      If i = 0
        i = j
        j + 1
      EndIf
    EndIf
  Wend
EndProcedure


#include <iterator>
#include <algorithm> // for std::inplace_merge
#include <functional> // for std::less

template<typename RandomAccessIterator, typename Order>
 void mergesort(RandomAccessIterator first, RandomAccessIterator last, Order order)
{
  if (last - first > 1)
  {
    RandomAccessIterator middle = first + (last - first) / 2;
    mergesort(first, middle, order);
    mergesort(middle, last, order);
    std::inplace_merge(first, middle, last, order);
  }
}

template<typename RandomAccessIterator>
 void mergesort(RandomAccessIterator first, RandomAccessIterator last)
{
  mergesort(first, last, std::less<typename std::iterator_traits<RandomAccessIterator>::value_type>());
}


(defn merge [left right]
  (cond (nil? left) right
        (nil? right) left
        :else (let [[l & *left] left
                    [r & *right] right]
                (if (<= l r) (cons l (merge *left right))
                             (cons r (merge left *right))))))

(defn merge-sort [list]
  (if (< (count list) 2)
    list
    (let [[left right] (split-at (/ (count list) 2) list)]
      (merge (merge-sort left) (merge-sort right)))))


mata
void insertion_sort(real vector a) {
	real scalar i, j, n, x

	n = length(a)
	for (i=2; i<=n; i++) {
		x = a[i]
		for (j=i-1; j>=1; j--) {
			if (a[j] <= x) break
			a[j+1] = a[j]
		}
		a[j+1] = x
	}
}
end


func insertionSort<T:Comparable>(inout list:[T]) {
    for i in 1..<list.count {
        var j = i

        while j > 0 && list[j - 1] > list[j] {
           swap(&list[j], &list[j - 1])
            j--
        }
    }
}


package require Tcl 8.5

proc insertionsort {m} {
    for {set i 1} {$i < [llength $m]} {incr i} {
        set val [lindex $m $i]
        set j [expr {$i - 1}]
        while {$j >= 0 && [lindex $m $j] > $val} {
            lset m [expr {$j + 1}] [lindex $m $j]
            incr j -1
        }
        lset m [expr {$j + 1}] $val
    }
    return $m
}

puts [insertionsort {8 6 4 2 1 3 5 7 9}] ;# => 1 2 3 4 5 6 7 8 9


{ X is array of LongInt }
Procedure QuickSort ( Left, Right : LongInt );
Var
  i, j,
  tmp, pivot : LongInt;         { tmp & pivot are the same type as the elements of array }
Begin
  i:=Left;
  j:=Right;
  pivot := X[(Left + Right) shr 1]; // pivot := X[(Left + Rigth) div 2]
  Repeat
    While pivot > X[i] Do inc(i);   // i:=i+1;
    While pivot < X[j] Do dec(j);   // j:=j-1;
    If i<=j Then Begin
      tmp:=X[i];
      X[i]:=X[j];
      X[j]:=tmp;
      dec(j);   // j:=j-1;
      inc(i);   // i:=i+1;
    End;
  Until i>j;
  If Left<j Then QuickSort(Left,j);
  If i<Right Then QuickSort(i,Right);
End;


[ dup size times
  [ i^ 0 > if
    [ dup i^ 1 - peek
      over i^ peek
      2dup > iff
        [ dip [ swap i^ poke ]
          swap i^ 1 - poke
          -1 step ]
        else 2drop ] ] ]       is gnomesort ( [ --> [ )


       IDENTIFICATION DIVISION.
       PROGRAM-ID.                      MERGESORT.
       AUTHOR.                          DAVE STRATFORD.
       DATE-WRITTEN.                    APRIL 2010.
       INSTALLATION.                    HEXAGON SYSTEMS LIMITED.
      ******************************************************************
      *                            MERGE SORT                          *
      *  The Merge sort uses a completely different paradigm, one of   *
      * divide and conquer, to many of the other sorts. The data set   *
      * is split into smaller sub sets upon which are sorted and then  *
      * merged together to form the final sorted data set.             *
      *  This version uses the recursive method. Split the data set in *
      * half and perform a merge sort on each half. This in turn splits*
      * each half again and again until each set is just one or 2 items*
      * long. A set of one item is already sorted so is ignored, a set *
      * of two is compared and swapped as necessary. The smaller data  *
      * sets are then repeatedly merged together to eventually form the*
      * full, sorted, set.                                             *
      *  Since cobol cannot do recursion this module only simulates it *
      * so is not as fast as a normal recursive version would be.      *
      *  Scales very well to larger data sets, its relative complexity *
      * means it is not suited to sorting smaller data sets: use an    *
      * Insertion sort instead as the Merge sort is a stable sort.     *
      ******************************************************************

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SOURCE-COMPUTER.                 ICL VME.
       OBJECT-COMPUTER.                 ICL VME.

       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT FA-INPUT-FILE  ASSIGN FL01.
           SELECT FB-OUTPUT-FILE ASSIGN FL02.

       DATA DIVISION.
       FILE SECTION.
       FD  FA-INPUT-FILE.
       01  FA-INPUT-REC.
         03  FA-DATA                    PIC 9(6).

       FD  FB-OUTPUT-FILE.
       01  FB-OUTPUT-REC                PIC 9(6).

       WORKING-STORAGE SECTION.
       01  WA-IDENTITY.
         03  WA-PROGNAME                PIC X(10) VALUE "MERGESORT".
         03  WA-VERSION                 PIC X(6) VALUE "000001".

       01  WB-TABLE.
         03  WB-ENTRY                   PIC 9(8) COMP SYNC OCCURS 100000
                                                 INDEXED BY WB-IX-1
                                                            WB-IX-2.

       01  WC-VARS.
         03  WC-SIZE                    PIC S9(8) COMP SYNC.
         03  WC-TEMP                    PIC S9(8) COMP SYNC.
         03  WC-START                   PIC S9(8) COMP SYNC.
         03  WC-MIDDLE                  PIC S9(8) COMP SYNC.
         03  WC-END                     PIC S9(8) COMP SYNC.

       01  WD-FIRST-HALF.
         03  WD-FH-MAX                  PIC S9(8) COMP SYNC.
         03  WD-ENTRY                   PIC 9(8) COMP SYNC OCCURS 50000
                                                 INDEXED BY WD-IX.

       01  WF-CONDITION-FLAGS.
         03  WF-EOF-FLAG                PIC X.
           88  END-OF-FILE              VALUE "Y".
         03  WF-EMPTY-FILE-FLAG         PIC X.
           88  EMPTY-FILE               VALUE "Y".

       01  WS-STACK.
      * This stack is big enough to sort a list of 1million items.
         03  WS-STACK-ENTRY OCCURS 20 INDEXED BY WS-STACK-TOP.
           05  WS-START                 PIC S9(8) COMP SYNC.
           05  WS-MIDDLE                PIC S9(8) COMP SYNC.
           05  WS-END                   PIC S9(8) COMP SYNC.
           05  WS-FS-FLAG               PIC X.
             88  FIRST-HALF             VALUE "F".
             88  SECOND-HALF            VALUE "S".
             88  WS-ALL                 VALUE "A".
           05  WS-IO-FLAG               PIC X.
             88  WS-IN                  VALUE "I".
             88  WS-OUT                 VALUE "O".

       PROCEDURE DIVISION.
       A-MAIN SECTION.
       A-000.
           PERFORM B-INITIALISE.

           IF NOT EMPTY-FILE
              PERFORM C-PROCESS.

           PERFORM D-FINISH.

       A-999.
           STOP RUN.

       B-INITIALISE SECTION.
       B-000.
           DISPLAY "*** " WA-PROGNAME " VERSION "
                          WA-VERSION " STARTING ***".

           MOVE ALL "N" TO WF-CONDITION-FLAGS.
           OPEN INPUT FA-INPUT-FILE.
           SET WB-IX-1 TO 0.

           READ FA-INPUT-FILE AT END MOVE "Y" TO WF-EOF-FLAG
                                                 WF-EMPTY-FILE-FLAG.

           PERFORM BA-READ-INPUT UNTIL END-OF-FILE.

           CLOSE FA-INPUT-FILE.

           SET WC-SIZE TO WB-IX-1.

       B-999.
           EXIT.

       BA-READ-INPUT SECTION.
       BA-000.
           SET WB-IX-1 UP BY 1.
           MOVE FA-DATA TO WB-ENTRY(WB-IX-1).

           READ FA-INPUT-FILE AT END MOVE "Y" TO WF-EOF-FLAG.

       BA-999.
           EXIT.

       C-PROCESS SECTION.
       C-000.
           DISPLAY "SORT STARTING".

           MOVE 1           TO WS-START(1).
           MOVE WC-SIZE     TO WS-END(1).
           MOVE "F"         TO WS-FS-FLAG(1).
           MOVE "I"         TO WS-IO-FLAG(1).
           SET WS-STACK-TOP TO 2.

           PERFORM E-MERGE-SORT UNTIL WS-OUT(1).

           DISPLAY "SORT FINISHED".

       C-999.
           EXIT.

       D-FINISH SECTION.
       D-000.
           OPEN OUTPUT FB-OUTPUT-FILE.
           SET WB-IX-1 TO 1.

           PERFORM DA-WRITE-OUTPUT UNTIL WB-IX-1 > WC-SIZE.

           CLOSE FB-OUTPUT-FILE.

           DISPLAY "*** " WA-PROGNAME " FINISHED ***".

       D-999.
           EXIT.

       DA-WRITE-OUTPUT SECTION.
       DA-000.
           WRITE FB-OUTPUT-REC FROM WB-ENTRY(WB-IX-1).
           SET WB-IX-1 UP BY 1.

       DA-999.
           EXIT.

      ******************************************************************
       E-MERGE-SORT SECTION.
      *=====================                                           *
      * This section controls the simulated recursion.                 *
      ******************************************************************
       E-000.
           IF WS-OUT(WS-STACK-TOP - 1)
              GO TO E-010.

           MOVE WS-START(WS-STACK-TOP - 1) TO WC-START.
           MOVE WS-END(WS-STACK-TOP - 1)   TO WC-END.

      * First check size of part we are dealing with.
           IF WC-END - WC-START = 0
      * Only 1 number in range, so simply set for output, and move on
              MOVE "O" TO WS-IO-FLAG(WS-STACK-TOP - 1)
              GO TO E-010.

           IF WC-END - WC-START = 1
      * 2 numbers, so compare and swap as necessary. Set for output
              MOVE "O" TO WS-IO-FLAG(WS-STACK-TOP - 1)
              IF WB-ENTRY(WC-START) > WB-ENTRY(WC-END)
                 MOVE WB-ENTRY(WC-START) TO WC-TEMP
                 MOVE WB-ENTRY(WC-END) TO WB-ENTRY(WC-START)
                 MOVE WC-TEMP TO WB-ENTRY(WC-END)
                 GO TO E-010
              ELSE
                 GO TO E-010.

      * More than 2, so split and carry on down
           COMPUTE WC-MIDDLE = ( WC-START + WC-END ) / 2.

           MOVE WC-START  TO WS-START(WS-STACK-TOP).
           MOVE WC-MIDDLE TO WS-END(WS-STACK-TOP).
           MOVE "F"       TO WS-FS-FLAG(WS-STACK-TOP).
           MOVE "I"       TO WS-IO-FLAG(WS-STACK-TOP).
           SET WS-STACK-TOP UP BY 1.

           GO TO E-999.

       E-010.
           SET WS-STACK-TOP DOWN BY 1.

           IF SECOND-HALF(WS-STACK-TOP)
              GO TO E-020.

           MOVE WS-START(WS-STACK-TOP - 1) TO WC-START.
           MOVE WS-END(WS-STACK-TOP - 1)   TO WC-END.
           COMPUTE WC-MIDDLE = ( WC-START + WC-END ) / 2 + 1.

           MOVE WC-MIDDLE TO WS-START(WS-STACK-TOP).
           MOVE WC-END    TO WS-END(WS-STACK-TOP).
           MOVE "S"       TO WS-FS-FLAG(WS-STACK-TOP).
           MOVE "I"       TO WS-IO-FLAG(WS-STACK-TOP).
           SET WS-STACK-TOP UP BY 1.

           GO TO E-999.

       E-020.
           MOVE WS-START(WS-STACK-TOP - 1) TO WC-START.
           MOVE WS-END(WS-STACK-TOP - 1)   TO WC-END.
           COMPUTE WC-MIDDLE = ( WC-START + WC-END ) / 2.
           PERFORM H-PROCESS-MERGE.
           MOVE "O" TO WS-IO-FLAG(WS-STACK-TOP - 1).

       E-999.
           EXIT.

      ******************************************************************
       H-PROCESS-MERGE SECTION.
      *========================                                        *
      * This section identifies which data is to be merged, and then   *
      * merges the two data streams into a single larger data stream.  *
      ******************************************************************
       H-000.
           INITIALISE WD-FIRST-HALF.
           COMPUTE WD-FH-MAX = WC-MIDDLE - WC-START + 1.
           SET WD-IX                        TO 1.

           PERFORM HA-COPY-OUT VARYING WB-IX-1 FROM WC-START BY 1
                               UNTIL WB-IX-1 > WC-MIDDLE.

           SET WB-IX-1 TO WC-START.
           SET WB-IX-2 TO WC-MIDDLE.
           SET WB-IX-2 UP BY 1.
           SET WD-IX   TO 1.

           PERFORM HB-MERGE UNTIL WD-IX > WD-FH-MAX OR WB-IX-2 > WC-END.

           PERFORM HC-COPY-BACK UNTIL WD-IX > WD-FH-MAX.

       H-999.
           EXIT.

       HA-COPY-OUT SECTION.
       HA-000.
           MOVE WB-ENTRY(WB-IX-1) TO WD-ENTRY(WD-IX).
           SET WD-IX UP BY 1.

       HA-999.
           EXIT.

       HB-MERGE SECTION.
       HB-000.
           IF WB-ENTRY(WB-IX-2) < WD-ENTRY(WD-IX)
              MOVE WB-ENTRY(WB-IX-2) TO WB-ENTRY(WB-IX-1)
              SET WB-IX-2            UP BY 1
           ELSE
              MOVE WD-ENTRY(WD-IX) TO WB-ENTRY(WB-IX-1)
              SET WD-IX            UP BY 1.

           SET WB-IX-1 UP BY 1.

       HB-999.
           EXIT.

       HC-COPY-BACK SECTION.
       HC-000.
           MOVE WD-ENTRY(WD-IX) TO WB-ENTRY(WB-IX-1).
           SET WD-IX            UP BY 1.
           SET WB-IX-1          UP BY 1.

       HC-999.
           EXIT.


:"INSERTION"
:L1→L2
:0→A
:Lbl L
:A+1→A
:A→B
:While B>0
:If L2(B)≤L2(B+1)
:Goto B
:L2(B)→C
:L2(B+1)→L2(B)
:C→L2(B+1)
:B-1→B
:End
:Lbl B
:If A<(dim(L2)-1)
:Goto L
:DelVar A
:DelVar B
:DelVar C
:Return


PRINT "Insertion sort:"
  n = FUNC (_InitArray)
  PROC _ShowArray (n)
  PROC _Insertionsort (n)
  PROC _ShowArray (n)
PRINT

END

_Insertionsort PARAM (1)               ' Insertion sort
  LOCAL (3)

  FOR [email protected] = 1 TO [email protected]
    [email protected] = @([email protected])
    [email protected] = [email protected]
    DO WHILE ([email protected]>0) * ([email protected] < @(ABS([email protected])))
        @([email protected]) = @([email protected])
        [email protected] = [email protected] - 1
    LOOP
    @([email protected]) = [email protected]
  NEXT
RETURN

_Swap PARAM(2)                         ' Swap two array elements
  PUSH @([email protected])
  @([email protected]) = @([email protected])
  @([email protected]) = POP()
RETURN

_InitArray                             ' Init example array
  PUSH 4, 65, 2, -31, 0, 99, 2, 83, 782, 1

  FOR i = 0 TO 9
    @(i) = POP()
  NEXT

RETURN (i)

_ShowArray PARAM (1)                   ' Show array subroutine
  FOR i = 0 TO [email protected]
    PRINT @(i),
  NEXT

  PRINT
RETURN


sub quick_sort {
    return @_ if @_ < 2;
    my $p = splice @_, int rand @_, 1;
    quick_sort(grep $_ < $p, @_), $p, quick_sort(grep $_ >= $p, @_);
}

my @a = (4, 65, 2, -31, 0, 99, 83, 782, 1);
@a = quick_sort @a;
print "@a\n";


#lang racket

;; Translation of the pseudo code
(define (gnome-sort1 a <=?)
  (define size (vector-length a))
  (define (swap i j)
    (define t (vector-ref a i))
    (vector-set! a i (vector-ref a j))
    (vector-set! a j t))
  (let loop ([i 1] [j 2])
    (when (< i size)
      (if (<=? (vector-ref a (sub1 i)) (vector-ref a i))
        (loop j (add1 j))
        (begin (swap (sub1 i) i)
               (let ([i (sub1 i)])
                 (if (zero? i)
                   (loop j (add1 j))
                   (loop i j)))))))
  a)
(gnome-sort1 (vector 3 2 1 4 5 6) <=)

;; a functional version, roughly like the Scheme entry
(define (gnome-sort2 l <=?)
  (match l
    [(list) l]
    [(list x xs ...)
     (let loop ([x `((,x) . ,xs)])
       (match x
         [`(,ps) ps]
         [`((,p . ,ps) ,n . ,ns)
          (loop (cond [(<=? n p)  `((,n ,p . ,ps) . ,ns)]
                      [(null? ps) `((,n) ,p . ,ns)]
                      [else       `(,ps ,n ,p . ,ns)]))]))]))
(gnome-sort2 '(3 2 1 4 5 6) <=)


import List;

public list[int] gnomeSort(a){
	i = 1;
	j = 2;
	while(i < size(a)){
		if(a[i-1] <= a[i]){
			i = j;
			j += 1;}
		else{
			temp = a[i-1];
			a[i-1] = a[i];
			a[i] = temp;
			i = i - 1;
			if(i == 0){
				i = j;
				j += 1;}}}
	return a;
}


# This is a simple version of mergesort that returns brand-new arrays.
# A more sophisticated version would do more in-place optimizations.
merge_sort = (arr) ->
  if arr.length <= 1
    return (elem for elem in arr)
  m = Math.floor(arr.length / 2)
  arr1 = merge_sort(arr.slice 0, m)
  arr2 = merge_sort(arr.slice m)
  result = []
  p1 = p2 = 0
  while true
    if p1 >= arr1.length
      if p2 >= arr2.length
        return result
      result.push arr2[p2]
      p2 += 1
    else if p2 >= arr2.length or arr1[p1] < arr2[p2]
      result.push arr1[p1]
      p1 += 1
    else
      result.push arr2[p2]
      p2 += 1

do ->
  console.log merge_sort [2,4,6,8,1,3,5,7,9,10,11,0,13,12]


(defun merge-sort (result-type sequence predicate)
   (let ((split (floor (length sequence) 2)))
     (if (zerop split)
       (copy-seq sequence)
       (merge result-type (merge-sort result-type (subseq sequence 0 split) predicate)
                          (merge-sort result-type (subseq sequence split)   predicate)
                          predicate))))


selectionsort() {
   read a
   test -n "$a" && ( selectionsort | sort -nm <(echo $a) -)
}


#import nat

insort = ~&i&& @hNCtX ~&r->lx ^\~&rt [email protected]


void insertion_sort(int[] array) {
  var count = 0;
  for (int i = 1; i < array.length; i++) {
    var val = array[i];
    var j = i;
    while (j > 0 && val < array[j - 1]) {
      array[j] = array[j - 1];
      j--;
    }
    array[j] = val;
  }
}

void main() {
  int[] array = {4, 65, 2, -31, 0, 99, 2, 83, 782};
  insertion_sort(array);
  foreach (int i in array)
    print("%d ", i);
}


with javascript_semantics

function quick_sort(sequence x)
--
-- put x into ascending order using recursive quick sort
--
    integer n = length(x)
    if n<2 then
        return x    -- already sorted (trivial case)
    end if

    integer mid = floor((n+1)/2),
            last = 1
    object midval = x[mid]
    x[mid] = x[1]
    for i=2 to n do
        object xi = x[i]
        if xi<midval then
            last += 1
            x[i] = x[last]
            x[last] = xi
        end if
    end for

    return quick_sort(x[2..last]) & {midval} & quick_sort(x[last+1..n])
end function

?quick_sort({5,"oranges","and",3,"apples"})


/*REXX program sorts an array using the gnome sort algorithm (elements contain blanks). */
call gen                                         /*generate the  @   stemmed array.     */
call show     'before sort'                      /*display the   before  array elements.*/
                             say copies('▒', 60) /*show a separator line between sorts. */
call gnomeSort  #                                /*invoke the well─known  gnome  sort.  */
call show     ' after sort'                      /*display the    after  array elements.*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
gen: @.=;  @.1= '---the seven virtues---';    @.4= "Hope"           ;    @.7= 'Justice'
           @.2= '=======================';    @.5= "Charity  [Love]";    @.8= 'Prudence'
           @.3= 'Faith'                  ;    @.6= "Fortitude"      ;    @.9= 'Temperance'
             do #=1  while @.#\==''; end;   #= #-1;   w= length(#);  return /*get #items*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
gnomeSort: procedure expose @.;  parse arg n;     k= 2            /*N: is number items. */
             do j=3  while k<=n;                  p= k - 1        /*P: is previous item.*/
             if @.p<<[email protected].k  then do;      k= j;    iterate;   end  /*order is OK so far. */
             _= @.p;       @.p= @.k;     @.k= _                   /*swap two @ entries. */
             k= k - 1;     if k==1  then k= j;    else j= j-1     /*test for 1st index. */
             end    /*j*/;                                return
/*──────────────────────────────────────────────────────────────────────────────────────*/
show:  do j=1  for #;   say '       element'  right(j, w)  arg(1)":"  @.j;   end;   return


aList = [ 5, 6, 1, 2, 9, 14, 15, 7, 8, 97]
gnomeSort(aList)
for i=1 to len(aList)
    see "" + aList[i] + " "
next

func gnomeSort a
     i = 2
     j = 3
     while i < len(a)
           if a[i-1] <= a[i]
              i = j
              j = j + 1
           else
              temp = a[i-1]
              a[i-1] = a[i]
              a[i] = temp
              i = i - 1
              if i = 1
                 i = j
                 j = j + 1 ok ok end


class Array
  def gnomesort!
    i, j = 1, 2
    while i < length
      if self[i-1] <= self[i]
        i, j = j, j+1
      else
        self[i-1], self[i] = self[i], self[i-1]
        i -= 1
        if i == 0
          i, j = j, j+1
        end
      end
    end
    self
  end
end
ary = [7,6,5,9,8,4,3,1,2,0]
ary.gnomesort!
# => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


def merge_sort(a : Array(Int32)) : Array(Int32)
  return a if a.size <= 1
  m = a.size // 2
  lt = merge_sort(a[0 ... m])
  rt = merge_sort(a[m .. -1])
  return merge(lt, rt)
end

def merge(lt : Array(Int32), rt : Array(Int32)) : Array(Int32)
  result = Array(Int32).new
  until lt.empty? || rt.empty?
    result << (lt.first < rt.first ? lt.shift : rt.shift)
  end
  return result + lt + rt
end

a = [7, 6, 5, 9, 8, 4, 3, 1, 2, 0]
puts merge_sort(a) # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


-- merge sort: sorting two lists by merging the sorted first
-- and second half of the list

sort :: ([a] -> [a] -> [a] -> Success) -> [a] -> [a] -> Success

sort merge xs ys =
   if length xs < 2 then ys =:= xs
   else sort merge (firsthalf xs) us
        & sort merge (secondhalf xs) vs
        & merge us vs ys
   where us,vs free

intMerge :: [Int] -> [Int] -> [Int] -> Success

intMerge []     ys     zs =  zs =:= ys
intMerge (x:xs) []     zs =  zs =:= x:xs
intMerge (x:xs) (y:ys) zs =
   if (x > y) then intMerge (x:xs) ys us & zs =:= y:us
              else intMerge xs (y:ys) vs & zs =:= x:vs
   where us,vs free

firsthalf  xs = take (length xs `div` 2) xs
secondhalf xs = drop (length xs `div` 2) xs

goal1 xs = sort intMerge [3,1,2] xs
goal2 xs = sort intMerge [3,1,2,5,4,8] xs
goal3 xs = sort intMerge [3,1,2,5,4,8,6,7,2,9,1,4,3] xs


Option Base 1
Private Function insertion_sort(s As Variant) As Variant
    Dim temp As Variant
    Dim j As Integer
    For i = 2 To UBound(s)
        temp = s(i)
        j = i - 1
        Do While s(j) > temp
            s(j + 1) = s(j)
            j = j - 1
            If j = 0 Then Exit Do
        Loop
        s(j + 1) = temp
    Next i
    insertion_sort = s
End Function

Public Sub main()
    s = [{4, 15, "delta", 2, -31, 0, "alpha", 19, "gamma", 2, 13, "beta", 782, 1}]
    Debug.Print "Before: ", Join(s, ", ")
    Debug.Print "After: ", Join(insertion_sort(s), "' ")
End Sub


Randomize
Dim n(9) 'nine is the upperbound.
         'since VBS arrays are 0-based, it will have 10 elements.
For L = 0 to 9
   n(L) = Int(Rnd * 32768)
Next

WScript.StdOut.Write "ORIGINAL : "
For L = 0 to 9
   WScript.StdOut.Write n(L) & ";"
Next

InsertionSort n

WScript.StdOut.Write vbCrLf & "  SORTED : "
For L = 0 to 9
   WScript.StdOut.Write n(L) & ";"
Next

'the function
Sub InsertionSort(theList)
   For insertionElementIndex = 1 To UBound(theList)
      insertionElement = theList(insertionElementIndex)
      j = insertionElementIndex - 1
      Do While j >= 0
         'necessary for BASICs without short-circuit evaluation
         If insertionElement < theList(j) Then
            theList(j + 1) = theList(j)
            j = j - 1
         Else
            Exit Do
         End If
      Loop
      theList(j + 1) = insertionElement
   Next
End Sub


F cocktailshiftingbounds(&A)
   V beginIdx = 0
   V endIdx = A.len - 1

   L beginIdx <= endIdx
      V newBeginIdx = endIdx
      V newEndIdx = beginIdx
      L(ii) beginIdx .< endIdx
         I A[ii] > A[ii + 1]
            swap(&A[ii + 1], &A[ii])
            newEndIdx = ii
      endIdx = newEndIdx

      L(ii) (endIdx .< beginIdx - 1).step(-1)
         I A[ii] > A[ii + 1]
            swap(&A[ii + 1], &A[ii])
            newBeginIdx = ii
      beginIdx = newBeginIdx + 1

V test1 = [7, 6, 5, 9, 8, 4, 3, 1, 2, 0]
cocktailshiftingbounds(&test1)
print(test1)


function quicksort($arr){
	$lte = $gt = array();
	if(count($arr) < 2){
		return $arr;
	}
	$pivot_key = key($arr);
	$pivot = array_shift($arr);
	foreach($arr as $val){
		if($val <= $pivot){
			$lte[] = $val;
		} else {
			$gt[] = $val;
		}
	}
	return array_merge(quicksort($lte),array($pivot_key=>$pivot),quicksort($gt));
}

$arr = array(1, 3, 5, 7, 9, 8, 6, 4, 2);
$arr = quicksort($arr);
echo implode(',',$arr);


fn gnome_sort<T: PartialOrd>(a: &mut [T]) {
    let len = a.len();
    let mut i: usize = 1;
    let mut j: usize = 2;
    while i < len {
        if a[i - 1] <= a[i] {
            // for descending sort, use >= for comparison
            i = j;
            j += 1;
        } else {
            a.swap(i - 1, i);
            i -= 1;
            if i == 0 {
                i = j;
                j += 1;
            }
        }
    }
}

fn main() {
    let mut v = vec![10, 8, 4, 3, 1, 9, 0, 2, 7, 5, 6];
    println!("before: {:?}", v);
    gnome_sort(&mut v);
    println!("after:  {:?}", v);
}


object GnomeSort {
  def gnomeSort(a: Array[Int]): Unit = {
    var (i, j) = (1, 2)
    while ( i < a.length)
      if (a(i - 1) <= a(i)) { i = j; j += 1 }
    else {
      val tmp = a(i - 1)
      a(i - 1) = a(i)
      a({i -= 1; i + 1}) = tmp
      i = if (i == 0) {j += 1; j - 1} else i
    }
  }
}


; supply comparison function, which returns true if first and second
; arguments are in order or equal.
(define (gnome-sort-compar in-order input-list)
  (let gnome ((p (list (car input-list)))
              (n (cdr input-list)))
    (if (null? n) ; no more flowerpots?
        p ; we're done
        (let ((prev-pot (car p))
              (next-pot (car n)))
          (if (in-order next-pot prev-pot)
              ; if the pots are in order, step forwards.
              ; otherwise, exchange the two pots, and step backwards.
              (gnome (cons next-pot p) ; Prev list grows
                     (cdr n)) ; Next list shorter by one
              (if (null? (cdr p)) ; are we at the beginning?
                  (gnome                    ; if so, we can't step back
                   (list next-pot)          ; simply exchange the pots without
                   (cons prev-pot (cdr n))) ; changing lengths of lists
                  (gnome
                   (cdr p) ; Prev list shorter by one
                   (cons next-pot (cons prev-pot (cdr n))))))))))


import std.stdio, std.algorithm, std.array, std.range;

T[] mergeSorted(T)(in T[] D) /*pure nothrow @safe*/ {
    if (D.length < 2)
        return D.dup;
    return [D[0 .. $ / 2].mergeSorted, D[$ / 2 .. $].mergeSorted]
           .nWayUnion.array;
}

void main() {
    [3, 4, 2, 5, 1, 6].mergeSorted.writeln;
}


void main() {
  MergeSortInDart sampleSort = MergeSortInDart();

  List<int> theResultingList = sampleSort.sortTheList([54, 89, 125, 47899, 32, 61, 42, 895647, 215, 345, 6, 21, 2, 78]);

  print('Here\'s the sorted list: ${theResultingList}');
}

/////////////////////////////////////

class MergeSortInDart {

  List<int> sortedList;

  // In Dart we often put helper functions at the bottom.
  // You could put them anywhere, we just like it this way
  // for organizational purposes. It's nice to be able to
  // read them in the order they're called.

  // Start here
  List<int> sortTheList(List<int> sortThis){
    // My parameters are listed vertically for readability. Dart
    // doesn't care how you list them, vertically or horizontally.
    sortedList = mSort(
      sortThis,
      sortThis.sublist(0, sortThis.length),
      sortThis.length,
    );
    return sortThis;
  }

  mSort(
    List<int> sortThisList,
    List<int> tempList,
    int thisListLength) {

    if (thisListLength == 1) {
      return;
    }

    // In Dart using ~/ is more efficient than using .floor()
    int middle = (thisListLength ~/ 2);

    // If you use something in a try/on/catch/finally block then
    // be sure to declare it outside the block (for scope)
    List<int> tempLeftList;

    // This was used for troubleshooting. It was left here to show
    // how a basic block try/on can be better than a debugPrint since
    // it won't print unless there's a problem.
    try {
      tempLeftList = tempList.sublist(0, middle);
    } on RangeError {
      print(
          'tempLeftList length = ${tempList.length}, thisListLength '
            'was supposedly $thisListLength and Middle was $middle');
    }

    // If you see "myList.getRange(x,y)" that's a sign the code is
    // from Dart 1 and needs to be updated. It's "myList.sublist" in Dart 2
    List<int> tempRightList = tempList.sublist(middle);

    // Left side.
    mSort(
      tempLeftList,
      sortThisList.sublist(0, middle),
      middle,
    );

    // Right side.
    mSort(
      tempRightList,
      sortThisList.sublist(middle),
      sortThisList.length - middle,
    );

    // Merge it.
    dartMerge(
      tempLeftList,
      tempRightList,
      sortThisList,
    );
  }

  dartMerge(
    List<int> leftSide,
    List<int> rightSide,
    List<int> sortThisList,
    ) {
    int index = 0;
    int elementValue;

    // This should be human readable.
    while (leftSide.isNotEmpty && rightSide.isNotEmpty) {
      if (rightSide[0] < leftSide[0]) {
        elementValue = rightSide[0];
        rightSide.removeRange(0, 1);
      } else {
        elementValue = leftSide[0];
        leftSide.removeRange(0, 1);
      }
      sortThisList[index++] = elementValue;
    }

    while (leftSide.isNotEmpty) {
      elementValue = leftSide[0];
      leftSide.removeRange(0, 1);
      sortThisList[index++] = elementValue;
    }

    while (rightSide.isNotEmpty) {
      elementValue = rightSide[0];
      rightSide.removeRange(0, 1);
      sortThisList[index++] = elementValue;
    }
    sortedList = sortThisList;
  }
}


fn insertion(mut arr []int) {
	for i in 1 .. arr.len {
		value := arr[i]
		mut j := i - 1
		for j >= 0 && arr[j] > value {
			arr[j + 1] = arr[j]
			j--
		}
		arr[j + 1] = value
	}
}

fn main() {
	mut arr := [4, 65, 2, -31, 0, 99, 2, 83, 782, 1]
	println('Input: ' + arr.str())
	insertion(mut arr)
	println('Output: ' + arr.str())
}


var insertionSort = Fn.new { |a|
    for (i in 1..a.count-1) {
        var v = a[i]
        var j = i - 1
        while (j >= 0 && a[j] > v) {
            a[j+1] = a[j]
            j = j - 1
        }
        a[j+1] = v
    }
}

var as = [ [4, 65, 2, -31, 0, 99, 2, 83, 782, 1], [7, 5, 2, 6, 1, 4, 2, 6, 3] ]
for (a in as) {
    System.print("Before: %(a)")
    insertionSort.call(a)
    System.print("After : %(a)")
    System.print()
}


*        Cocktail sort with shifting bounds 10/05/2020
COCKSHIS CSECT
         USING  COCKSHIS,R13       base register
         B      72(R15)            skip savearea
         DC     17F'0'             savearea
         SAVE   (14,12)            save previous context
         ST     R13,4(R15)         link backward
         ST     R15,8(R13)         link forward
         LR     R13,R15            set addressability
* Sort
         LA     R0,1               1
         ST     R0,BEGIDX          begIdx=LBound(A)
         L      R0,N               n
         BCTR   R0,0               n-1
         ST     R0,ENDIDX          endIdx=UBound(A)-1
         L      R1,BEGIDX          begIdx
    DO WHILE=(C,R1,LE,ENDIDX)      while begIdx<=endIdx
         MVC    NWBEGIDX,ENDIDX      nwbegIdx=endIdx
         MVC    NWENDIDX,BEGIDX      nwendIdx=begIdx
         L      RI,BEGIDX            i=begIdx
    DO WHILE=(C,RI,LE,ENDIDX)        do i=1 to endIdx
         LR     R1,RI                  i
         SLA    R1,2                   .
         LA     R2,A-4(R1)             @a(i)
         LA     R3,A(R1)               @a(i+1)
         L      R4,0(R2)               r4=a(i)
         L      R5,0(R3)               r5=a(i+1)
       IF    CR,R4,GT,R5 THEN          if a(i)>a(i+1) then
         ST     R5,0(R2)                 a(i)=r5
         ST     R4,0(R3)                 a(i+1)=r4
         ST     RI,NWENDIDX              nwendIdx=i
       ENDIF    ,                      end if
         LA     RI,1(RI)               i=i+1
    ENDDO       ,                    end do
         L      R1,NWENDIDX          nwendIdx
         BCTR   R1,0                 -1
         ST     R1,ENDIDX            endIdx=nwendIdx-1
         LR     RI,R1                endIdx
    DO WHILE=(C,RI,GE,BEGIDX)        do i=endIdx to begIdx by -1
         LR     R1,RI                  i
         SLA    R1,2                   .
         LA     R2,A-4(R1)             @a(i)
         LA     R3,A(R1)               @a(i+1)
         L      R4,0(R2)               r4=a(i)
         L      R5,0(R3)               r5=a(i+1)
       IF    CR,R4,GT,R5 THEN          if a(i)>a(i+1) then
         ST     R5,0(R2)                 a(i)=r5
         ST     R4,0(R3)                 a(i+1)=r4
         ST     RI,NWBEGIDX              nwbegIdx=i
       ENDIF    ,                      end if
         BCTR   RI,0                   i=i-1
    ENDDO       ,                    end do
         L      R1,NWBEGIDX          nwbegIdx
         LA     R1,1(R1)             +1
         ST     R1,BEGIDX            begIdx=nwbegIdx+1
    ENDDO       ,                  endwhile
* Display sorted list
         LA     R3,PG              pgi=0
         LA     RI,1               i=1
       DO     WHILE=(C,RI,LE,N)    do i=1 to n
         LR     R1,RI                i
         SLA    R1,2                 .
         L      R2,A-4(R1)           a(i)
         XDECO  R2,XDEC              edit a(i)
         MVC    0(4,R3),XDEC+8       output a(i)
         LA     R3,4(R3)             pgi=pgi+4
         LA     RI,1(RI)             i=i+1
       ENDDO    ,                  end do
         XPRNT  PG,L'PG            print buffer
         L      R13,4(0,R13)       restore previous savearea pointer
         RETURN (14,12),RC=0       restore registers from calling save
A        DC     F'4',F'65',F'2',F'-31',F'0',F'99',F'2',F'83'
         DC     F'782',F'1',F'45',F'82',F'69',F'82',F'104',F'58'
         DC     F'88',F'112',F'89',F'74'
N        DC     A((N-A)/L'A)       number of items of a
PG       DC     CL80' '            buffer
XDEC     DS     CL12               temp for xdeco
BEGIDX   DS     F                  begIdx
ENDIDX   DS     F                  endIdx
NWBEGIDX DS     F                  nwbegIdx
NWENDIDX DS     F                  nwendIdx
         REGEQU
RI       EQU    6                  i
         END    COCKSHIS


/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program cocktailSortbound64.s  */

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeConstantesARM64.inc"

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessSortOk:       .asciz "Table sorted.\n"
szMessSortNok:      .asciz "Table not sorted !!!!!.\n"
sMessResult:        .asciz "Value  : @ \n"
szCarriageReturn:   .asciz "\n"

.align 4
//TableNumber:      .quad   1,3,6,2,5,9,10,8,4,7
TableNumber:     .quad   10,9,8,7,6,-5,4,3,2,1
                 .equ NBELEMENTS, (. - TableNumber) / 8
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:       .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                              // entry of program
    ldr x0,qAdrTableNumber                         // address number table
    mov x1,0
    mov x2,NBELEMENTS                              // number of élements
    bl cocktailSortBound
    ldr x0,qAdrTableNumber                         // address number table
    bl displayTable

    ldr x0,qAdrTableNumber                         // address number table
    mov x1,NBELEMENTS                              // number of élements
    bl isSorted                                    // control sort
    cmp x0,1                                       // sorted ?
    beq 1f
    ldr x0,qAdrszMessSortNok                       // no !! error sort
    bl affichageMess
    b 100f
1:                                                 // yes
    ldr x0,qAdrszMessSortOk
    bl affichageMess
100:                                               // standard end of the program
    mov x0,0                                       // return code
    mov x8,EXIT                                    // request to exit program
    svc 0                                          // perform the system call

qAdrsZoneConv:            .quad sZoneConv
qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrsMessResult:          .quad sMessResult
qAdrTableNumber:          .quad TableNumber
qAdrszMessSortOk:         .quad szMessSortOk
qAdrszMessSortNok:        .quad szMessSortNok
/******************************************************************/
/*     control sorted table                                   */
/******************************************************************/
/* x0 contains the address of table */
/* x1 contains the number of elements  > 0  */
/* x0 return 0  if not sorted   1  if sorted */
isSorted:
    stp x2,lr,[sp,-16]!              // save  registers
    stp x3,x4,[sp,-16]!              // save  registers
    mov x2,0
    ldr x4,[x0,x2,lsl 3]
1:
    add x2,x2,1
    cmp x2,x1
    bge 99f
    ldr x3,[x0,x2, lsl 3]
    cmp x3,x4
    blt 98f
    mov x4,x3
    b 1b
98:
    mov x0,0                       // not sorted
    b 100f
99:
    mov x0,1                       // sorted
100:
    ldp x3,x4,[sp],16              // restaur  2 registers
    ldp x2,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/******************************************************************/
/*         cocktail sort  Bound                                            */
/******************************************************************/
/* x0 contains the address of table */
/* x1 contains the first element    */
/* x2 contains the number of element */
cocktailSortBound:
    stp x1,lr,[sp,-16]!        // save  registers
    stp x2,x3,[sp,-16]!        // save  registers
    stp x4,x5,[sp,-16]!        // save  registers
    stp x6,x7,[sp,-16]!        // save  registers
    stp x8,x9,[sp,-16]!        // save  registers
    sub x2,x2,2                // compute endidx = n - 2
                               // and r1 = beginidx
1:                             // start loop 1
    cmp x1,x2
    bgt 100f
    mov x8,x1                  // newbeginidx
    mov x7,x2                  // newendidx
    mov x3,x1                  // start index

2:                             // start loop 2
    add x4,x3,1
    ldr x5,[x0,x3,lsl 3]       // load value A[j]
    ldr x6,[x0,x4,lsl 3]       // load value A[j+1]
    cmp x6,x5                  // compare value
    bge 3f
    str x6,[x0,x3,lsl 3]       // if smaller inversion
    str x5,[x0,x4,lsl 3]
    mov x7,x3                   // and mov indice to newendidx
3:
    add x3,x3,1                // increment index j
    cmp x3,x2                  // end ?
    ble 2b                     // no -> loop 2
    sub x2,x7,1                // endidx = newendidx - 1

    bl displayTable
    mov x3,x2                  // indice
4:
    add x4,x3,1
    ldr x5,[x0,x3,lsl 3]       // load value A[j]
    ldr x6,[x0,x4,lsl 3]       // load value A[j+1]
    cmp x6,x5                  // compare value
    bge 5f
    str x6,[x0,x3,lsl 3]       // if smaller inversion
    str x5,[x0,x4,lsl 3]
    mov x8,x3                  // newbeginidx = indice
5:
    sub x3,x3,1                // decrement index j
    cmp x3,x1                  // end ?
    bge 4b                     // no -> loop 2

    add x1,x8,1                // beginidx = newbeginidx
    b 1b                       // loop 1

100:
    ldp x8,x9,[sp],16          // restaur  2 registers
    ldp x6,x7,[sp],16          // restaur  2 registers
    ldp x4,x5,[sp],16          // restaur  2 registers
    ldp x2,x3,[sp],16          // restaur  2 registers
    ldp x1,lr,[sp],16          // restaur  2 registers
    ret                        // return to address lr x30

/******************************************************************/
/*      Display table elements                                */
/******************************************************************/
/* x0 contains the address of table */
displayTable:
    stp x1,lr,[sp,-16]!              // save  registers
    stp x2,x3,[sp,-16]!              // save  registers
    mov x2,x0                        // table address
    mov x3,0
1:                                   // loop display table
    ldr x0,[x2,x3,lsl 3]
    ldr x1,qAdrsZoneConv
    bl conversion10S                  // décimal conversion
    ldr x0,qAdrsMessResult
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc            // insert result at @ character
    bl affichageMess                 // display message
    add x3,x3,1
    cmp x3,NBELEMENTS - 1
    ble 1b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    mov x0,x2                       // table address
100:
    ldp x2,x3,[sp],16               // restaur  2 registers
    ldp x1,lr,[sp],16               // restaur  2 registers
    ret                             // return to address lr x30
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"


PROC PrintArray(INT ARRAY a INT size)
  INT i

  Put('[)
  FOR i=0 TO size-1
  DO
    IF i>0 THEN Put(' ) FI
    PrintI(a(i))
  OD
  Put(']) PutE()
RETURN

PROC CoctailShakerSort(INT ARRAY a INT size)
  INT begIdx,endIdx,newBegIdx,newEndIdx,i,tmp

  begIdx=0 endIdx=size-2
  WHILE begIdx<=endIdx
  DO
    newBegIdx=endIdx
    newEndIdx=begIdx
    i=begIdx
    WHILE i<=endIdx
    DO
      IF a(i)>a(i+1) THEN
        tmp=a(i) a(i)=a(i+1) a(i+1)=tmp
        newEndIdx=i
      FI
      i==+1
    OD
    endIdx=newEndIdx-1

    i=endIdx
    WHILE i>=begIdx
    DO
      IF a(i)>a(i+1) THEN
        tmp=a(i) a(i)=a(i+1) a(i+1)=tmp
        newBegIdx=i
      FI
      i==-1
    OD
    begIdx=newBegIdx+1
  OD
RETURN

PROC Test(INT ARRAY a INT size)
  PrintE("Array before sort:")
  PrintArray(a,size)
  CoctailShakerSort(a,size)
  PrintE("Array after sort:")
  PrintArray(a,size)
  PutE()
RETURN

PROC Main()
  INT ARRAY
    a(10)=[1 4 65535 0 3 7 4 8 20 65530],
    b(21)=[10 9 8 7 6 5 4 3 2 1 0
      65535 65534 65533 65532 65531
      65530 65529 65528 65527 65526],
    c(8)=[101 102 103 104 105 106 107 108],
    d(12)=[1 65535 1 65535 1 65535 1
      65535 1 65535 1 65535]

  Test(a,10)
  Test(b,21)
  Test(c,8)
  Test(d,12)
RETURN


begin
    comment Sorting algorithms/Cocktail sort with shifting bounds - Algol 60;
    integer nA;
    nA:=20;

    begin
        integer array A[1:nA];

        procedure cocktailsort(lb,ub);
        value lb,ub; integer lb,ub;
        begin
            integer i,lbx,ubx;
            boolean swapped;
            lbx:=lb; ubx:=ub-1; swapped :=true;
            for i:=1 while swapped do begin

                procedure swap(i); value i; integer i;
                begin
                    integer temp;
                    temp  :=A[i];
                    A[i]  :=A[i+1];
                    A[i+1]:=temp;
                    swapped:=true
                end swap;

                swapped:=false;
                for i:=lbx step  1 until ubx do if A[i]>A[i+1] then swap(i);
                if swapped
                then begin
                    for i:=ubx step -1 until lbx do if A[i]>A[i+1] then swap(i);
                    ubx:=ubx-1; lbx:=lbx+1
                end
            end
        end cocktailsort;

        procedure inittable(lb,ub);
        value lb,ub; integer lb,ub;
        begin
            integer i;
            for i:=lb step 1 until ub do A[i]:=entier(rand*100)
        end inittable;

        procedure writetable(lb,ub);
        value lb,ub; integer lb,ub;
        begin
            integer i;
            for i:=lb step 1 until ub do outinteger(1,A[i]);
            outstring(1,"\n")
        end writetable;

        nA:=20;
        inittable(1,nA);
        writetable(1,nA);
        cocktailsort(1,nA);
        writetable(1,nA)
    end
end


/* ARM assembly Raspberry PI  */
/*  program cocktailSortBound.s  */

 /* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessSortOk:       .asciz "Table sorted.\n"
szMessSortNok:      .asciz "Table not sorted !!!!!.\n"
sMessResult:        .asciz "Value  : @ \n"
szCarriageReturn:   .asciz "\n"

.align 4
TableNumber:      .int   1,3,6,2,5,9,10,8,4,7
#TableNumber:       .int   10,9,8,7,6,-5,4,3,2,1
                   .equ NBELEMENTS, (. - TableNumber) / 4
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:            .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                              @ entry of program

1:
    ldr r0,iAdrTableNumber                         @ address number table
    mov r1,#0
    mov r2,#NBELEMENTS                             @ number of élements
    bl cocktailSortBound
    ldr r0,iAdrTableNumber                         @ address number table
    bl displayTable

    ldr r0,iAdrTableNumber                         @ address number table
    mov r1,#NBELEMENTS                             @ number of élements
    bl isSorted                                    @ control sort
    cmp r0,#1                                      @ sorted ?
    beq 2f
    ldr r0,iAdrszMessSortNok                       @ no !! error sort
    bl affichageMess
    b 100f
2:                                                 @ yes
    ldr r0,iAdrszMessSortOk
    bl affichageMess
100:                                               @ standard end of the program
    mov r0, #0                                     @ return code
    mov r7, #EXIT                                  @ request to exit program
    svc #0                                         @ perform the system call

iAdrszCarriageReturn:     .int szCarriageReturn
iAdrsMessResult:          .int sMessResult
iAdrTableNumber:          .int TableNumber
iAdrszMessSortOk:         .int szMessSortOk
iAdrszMessSortNok:        .int szMessSortNok
/******************************************************************/
/*     control sorted table                                   */
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains the number of elements  > 0  */
/* r0 return 0  if not sorted   1  if sorted */
isSorted:
    push {r2-r4,lr}                                    @ save registers
    mov r2,#0
    ldr r4,[r0,r2,lsl #2]
1:
    add r2,#1
    cmp r2,r1
    movge r0,#1
    bge 100f
    ldr r3,[r0,r2, lsl #2]
    cmp r3,r4
    movlt r0,#0
    blt 100f
    mov r4,r3
    b 1b
100:
    pop {r2-r4,lr}
    bx lr                                              @ return
/******************************************************************/
/*         cocktail Sort                                          */
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains the first element    */
/* r2 contains the number of element */
cocktailSortBound:
    push {r1-r9,lr}           @ save registers
    sub r2,r2,#2              @ compute endidx = n - 2
                              @ and r1= beginidx
1:                            @ start loop 1
    cmp r1,r2                 @ compare endidx beginidx
    bgt 100f
    mov r8,r1                 @ newbeginidx
    mov r7,r2                 @ newendidx
    mov r3,r1                 @ indice
2:                            @ start loop 2
    add r4,r3,#1
    ldr r5,[r0,r3,lsl #2]     @ load value A[j]
    ldr r6,[r0,r4,lsl #2]     @ load value A[j+1]
    cmp r6,r5                 @ compare value
    strlt r6,[r0,r3,lsl #2]   @ if smaller inversion
    strlt r5,[r0,r4,lsl #2]
    movlt r7,r3               @ and mov indice to newendidx
    add r3,#1                 @ increment indice
    cmp r3,r2                 @ end ?
    ble 2b                    @ no -> loop 2

    sub r2,r7,#1              @ endidx = newendidx

    //bl displayTable
    mov r3,r2                 @ indice
3:
    add r4,r3,#1
    ldr r5,[r0,r3,lsl #2]     @ load value A[j]
    ldr r6,[r0,r4,lsl #2]     @ load value A[j+1]
    cmp r6,r5                 @ compare value
    strlt r6,[r0,r3,lsl #2]   @ if smaller inversion
    strlt r5,[r0,r4,lsl #2]
    movlt r8,r3               @ newbeginidx = indice
    sub r3,#1                 @ decrement indice
    cmp r3,r1                 @ end ?
    bge 3b                    @ no -> loop 3

    //bl displayTable
    add r1,r8,#1              @ beginidx = newbeginidx + 1
    b 1b                       @ loop 1

100:
    pop {r1-r9,lr}
    bx lr                                                  @ return

/******************************************************************/
/*      Display table elements                                */
/******************************************************************/
/* r0 contains the address of table */
displayTable:
    push {r0-r3,lr}                                    @ save registers
    mov r2,r0                                          @ table address
    mov r3,#0
1:                                                     @ loop display table
    ldr r0,[r2,r3,lsl #2]
    ldr r1,iAdrsZoneConv                               @
    bl conversion10S                                    @ décimal conversion
    ldr r0,iAdrsMessResult
    ldr r1,iAdrsZoneConv                               @ insert conversion
    bl strInsertAtCharInc
    bl affichageMess                                   @ display message
    add r3,#1
    cmp r3,#NBELEMENTS - 1
    ble 1b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
100:
    pop {r0-r3,lr}
    bx lr
iAdrsZoneConv:           .int sZoneConv
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"


qsort([])    = [].
qsort([H|T]) = qsort([E : E in T, E =< H])
               ++ [H] ++
               qsort([E : E in T, E > H]).


(de quicksort (L)
   (if (cdr L)
      (let Pivot (car L)
          (append (quicksort (filter '((A) (< A Pivot)) (cdr L)))
                             (filter '((A) (= A Pivot))      L )
                  (quicksort (filter '((A) (> A Pivot)) (cdr L)))) )
      L) )


class Array {
    method gnomesort {
        var (i=1, j=2);
        var len = self.len;
        while (i < len) {
            if (self[i-1] <= self[i]) {
                (i, j) = (j, j+1);
            }
            else {
                self[i-1, i] = self[i, i-1];
                if (--i == 0) {
                    (i, j) = (j, j+1);
                }
            }
        }
        return self;
    }
}

var ary = [7,6,5,9,8,4,3,1,2,0];
say ary.gnomesort;


Smalltalk at: #gnomesort put: nil.

"Utility"
OrderedCollection extend [
  swap: a with: b [ |t|
      t := self at: a.
      self at: a put: b.
      self at: b put: t
  ]
].

"Gnome sort as block closure"
gnomesort := [ :c |
  |i j|
  i := 2. j := 3.
  [ i <= (c size) ]
    whileTrue: [
       (c at: (i-1)) <= (c at: i)
          ifTrue: [
             i := j copy.
             j := j + 1.
          ]
          ifFalse: [
             c swap: (i-1) with: i.
             i := i - 1.
             i == 1
               ifTrue: [
                  i := j copy.
                  j := j + 1
               ]
          ]
    ]
].


def merge(var xs :List, var ys :List) {
    var result := []
    while (xs =~ [x] + xr && ys =~ [y] + yr) {
        if (x <= y) {
            result with= x
            xs := xr
        } else {
            result with= y
            ys := yr
        }
    }
    return result + xs + ys
}

def sort(list :List) {
    if (list.size() <= 1) { return list }
    def split := list.size() // 2
    return merge(sort(list.run(0, split)),
                 sort(list.run(split)))
}


code ChOut=8, IntOut=11;

proc InsertionSort(A, L);       \Sort array A of length L
int  A, L;
int  I, J, V;
[for I:= 1 to L-1 do
    [V:= A(I);
    J:= I-1;
    while J>=0 and A(J)>V do
        [A(J+1):= A(J);
        J:= J-1;
        ];
    A(J+1):= V;
    ];
];

int A, I;
[A:= [3, 1, 4, 1, -5, 9, 2, 6, 5, 4];
InsertionSort(A, 10);
for I:= 0 to 10-1 do [IntOut(0, A(I));  ChOut(0, ^ )];
]


sub InsertionSort (matriz())
    for i = 1 to arraysize(matriz(),1)
        valor = matriz(i)
        j = i - 1
        while (j >= 0) and (valor < matriz(j))
              matriz(j + 1) = matriz(j)
              j = j - 1
        wend
        matriz(j + 1) = valor
    next i
end sub

//--------------------------
dim array(10)
print "Antes de ordenar:"
for i = 1 to 10
    array(i) = int(ran(32768))
    print array(i), " ";
next i
print
print "\nDespues de ordenar:"

InsertionSort(array())

for i = 1 to 10
    print array(i), " ";
next i
print
end


func insertionSort(&A) {
  for(i = 2; i <= numberof(A); i++) {
    value = A(i);
    j = i - 1;
    while(j >= 1 && A(j) > value) {
      A(j+1) = A(j);
      j--;
    }
    A(j+1) = value;
  }
}


cocktailShiftSort: function [items][
    a: new items
    beginIdx: 0
    endIdx: (size a)-2

    while [beginIdx =< endIdx][
        newBeginIdx: endIdx
        newEndIdx: beginIdx

        loop beginIdx..endIdx 'i [
            if a\[i] > a\[i+1] [
                tmp: a\[i]
                a\[i]: a\[i+1]
                a\[i+1]: tmp
                newEndIdx: i
            ]
        ]

        endIdx: newEndIdx - 1

        loop endIdx..beginIdx 'i [
            if a\[i] > a\[i+1] [
                tmp: a\[i]
                a\[i]: a\[i+1]
                a\[i+1]: tmp
                newBeginIdx: i
            ]
        ]

        beginIdx: newBeginIdx - 1
    ]
    return a
]

print cocktailShiftSort [3 1 2 8 5 7 9 4 6]


cocktailShakerSort(A){
    beginIdx := 1
    endIdx := A.Count() - 1
    while (beginIdx <= endIdx) {
        newBeginIdx := endIdx
        newEndIdx := beginIdx
        ii := beginIdx
        while (ii <= endIdx) {
            if (A[ii] > A[ii + 1]) {
                tempVal := A[ii], A[ii] := A[ii+1], A[ii+1] := tempVal
                newEndIdx := ii
            }
            ii++
        }
        endIdx := newEndIdx - 1
        ii := endIdx
        while (ii >= beginIdx) {
            if (A[ii] > A[ii + 1]) {
                tempVal := A[ii], A[ii] := A[ii+1], A[ii+1] := tempVal
                newBeginIdx := ii
            }
            ii--
        }
        beginIdx := newBeginIdx + 1
    }
}


#include <stdio.h>
#include <string.h>

void swap(char* p1, char* p2, size_t size) {
    for (; size-- > 0; ++p1, ++p2) {
        char tmp = *p1;
        *p1 = *p2;
        *p2 = tmp;
    }
}

void cocktail_shaker_sort(void* base, size_t count, size_t size,
                          int (*cmp)(const void*, const void*)) {
    char* begin = base;
    char* end = base + size * count;
    if (end == begin)
        return;
    for (end -= size; begin < end; ) {
        char* new_begin = end;
        char* new_end = begin;
        for (char* p = begin; p < end; p += size) {
            char* q = p + size;
            if (cmp(p, q) > 0) {
                swap(p, q, size);
                new_end = p;
            }
        }
        end = new_end;
        for (char* p = end; p > begin; p -= size) {
            char* q = p - size;
            if (cmp(q, p) > 0) {
                swap(p, q, size);
                new_begin = p;
            }
        }
        begin = new_begin;
    }
}

int string_compare(const void* p1, const void* p2) {
    const char* const* s1 = p1;
    const char* const* s2 = p2;
    return strcmp(*s1, *s2);
}

void print(const char** a, size_t len) {
    for (size_t i = 0; i < len; ++i)
        printf("%s ", a[i]);
    printf("\n");
}

int main() {
    const char* a[] = { "one", "two", "three", "four", "five",
        "six", "seven", "eight" };
    const size_t len = sizeof(a)/sizeof(a[0]);
    printf("before: ");
    print(a, len);
    cocktail_shaker_sort(a, len, sizeof(char*), string_compare);
    printf("after: ");
    print(a, len);
    return 0;
}


DCL (T(20)) FIXED BIN(31);   /* scratch space of length N */

QUICKSORT: PROCEDURE (A,AMIN,AMAX,N) RECURSIVE ;
   DECLARE (A(*))              FIXED BIN(31);
   DECLARE (N,AMIN,AMAX)       FIXED BIN(31) NONASGN;
   DECLARE (I,J,IA,IB,IC,PIV)  FIXED BIN(31);
   DECLARE (P,Q)               POINTER;
   DECLARE (AP(1))             FIXED BIN(31) BASED(P);

   IF(N <= 1)THEN RETURN;
   IA=0; IB=0; IC=N+1;
   PIV=(AMIN+AMAX)/2;
   DO I=1 TO N;
      IF(A(I) < PIV)THEN DO;
         IA+=1; A(IA)=A(I);
      END; ELSE IF(A(I) > PIV) THEN DO;
         IC-=1; T(IC)=A(I);
      END; ELSE DO;
         IB+=1; T(IB)=A(I);
      END;
   END;
   DO I=1  TO IB; A(I+IA)=T(I);   END;
   DO I=IC TO N;  A(I)=T(N+IC-I); END;
   P=ADDR(A(IC));
   IC=N+1-IC;
   IF(IA > 1) THEN CALL QUICKSORT(A, AMIN, PIV-1,IA);
   IF(IC > 1) THEN CALL QUICKSORT(AP,PIV+1,AMAX, IC);
   RETURN;
END QUICKSORT;
 MINMAX: PROC(A,AMIN,AMAX,N);
   DCL (AMIN,AMAX) FIXED BIN(31),
       (N,A(*))    FIXED BIN(31) NONASGN ;
   DCL (I,X,Y) FIXED BIN(31);

   AMIN=A(N); AMAX=AMIN;
   DO I=1 TO N-1;
      X=A(I); Y=A(I+1);
      IF (X < Y)THEN DO;
         IF (X < AMIN) THEN AMIN=X;
         IF (Y > AMAX) THEN AMAX=Y;
       END; ELSE DO;
          IF (X > AMAX) THEN AMAX=X;
          IF (Y < AMIN) THEN AMIN=Y;
       END;
   END;
   RETURN;
END MINMAX;
CALL MINMAX(A,AMIN,AMAX,N);
CALL QUICKSORT(A,AMIN,AMAX,N);


*** GNOME SORT *****************************************************************
* GNOME(V)    -- gnome sort of the numerical vector V.
*** HELPER FUNCTIONS ***********************************************************
* IDXMAX(V)   -- highest index of vector V.
* IDXMIN(V)   -- lowest index of vector V.
* NUMBER(V)   -- succeeds if V is some form of numerical data, fails otherwise.
* NUMBERS(V)  -- succeeds iff all elements of vector V are numerical
* SWAP(A,B)   -- swaps the values of two variables (named with .var).
* VECTOR(V)   -- succeeds iff V is a vector.
********************************************************************************
  define('GNOME(V)I,J,K,L,H,T')
*
  define('IDXMAX(V)')
  define('IDXMIN(V)')
  define('NUMBER(V)')
  define('NUMBERS(V)I,M')
  define('SWAP(SWAP_PARAMETER_VAR_A,SWAP_PARAMETER_VAR_B)')
  define('VECTOR(V)')
  :(GNOME.END)

****************************************
* GNOME FUNCTION                       *
****************************************
GNOME         numbers(v)                                  :F(FRETURN)
              gnome = copy(v)
              l = idxmin(v) ; h = idxmax(v) ; i = l + 1
GNOME.LOOP    j = i - 1
              le(i, l)                                    :S(GNOME.FORWARD)
              gt(i,h)                                     :S(RETURN)
              le(gnome<j>, gnome<i>)                      :S(GNOME.FORWARD)
              swap(.gnome<j>, .gnome<i>)
              i = i - 1                                   :(GNOME.LOOP)
GNOME.FORWARD i = i + 1                                   :(GNOME.LOOP)

****************************************
* HELPER FUNCTIONS                     *
****************************************
IDXMAX        vector(v)                                   :F(FRETURN)
              prototype(v) ':' span('-' &digits) . idxmax :S(RETURN)F(IDXMAX.NORM)
IDXMAX.NORM   idxmax = prototype(v)                       :(RETURN)
****************************************
IDXMIN        vector(v)                                   :F(FRETURN)
              prototype(v) span('-' &digits) . idxmin ':' :S(RETURN)F(IDXMIN.NORM)
IDXMIN.NORM   idxmin = 1                                  :(RETURN)
****************************************
NUMBER      ident(datatype(v), 'INTEGER')                 :S(RETURN)
            ident(datatype(v), 'REAL')                    :S(RETURN)F(FRETURN)
****************************************
NUMBERS       vector(v)                                   :F(FRETURN)
              i = idxmin(v) ; m = idxmax(v)
NUMBERS.LOOP  le(i,m)                                     :F(RETURN)
              number(v<i>)                                :F(FRETURN)
              i = i + 1                                   :(NUMBERS.LOOP)
****************************************
SWAP        SWAP = $SWAP_PARAMETER_VAR_A
            $SWAP_PARAMETER_VAR_A = $SWAP_PARAMETER_VAR_B
            $SWAP_PARAMETER_VAR_B = SWAP
            SWAP =                                        :(RETURN)
****************************************
VECTOR        ident(v)                                    :S(FRETURN)
              prototype(v) ','                            :S(FRETURN)F(RETURN)
****************************************
GNOME.END


func gnomeSort<T: Comparable>(_ a: inout [T]) {
    var i = 1
    var j = 2
    while i < a.count {
        if a[i - 1] <= a[i] {
            i = j
            j += 1
        } else {
            a.swapAt(i - 1, i)
            i -= 1
            if i == 0 {
                i = j
                j += 1
            }
        }
    }
}

var array = [10, 8, 4, 3, 1, 9, 0, 2, 7, 5, 6]
print("before: \(array)")
gnomeSort(&array)
print(" after: \(array)")


package require Tcl 8.5
package require struct::list

proc gnomesort {a} {
    set i 1
    set j 2
    set size [llength $a]
    while {$i < $size} {
        if {[lindex $a [expr {$i - 1}]] <= [lindex $a $i]} {
            set i $j
            incr j
        } else {
            struct::list swap a [expr {$i - 1}] $i
            incr i -1
            if {$i == 0} {
                set i $j
                incr j
            }
        }
    }
    return $a
}

puts [gnomesort {8 6 4 2 1 3 5 7 9}] ;# => 1 2 3 4 5 6 7 8 9


subr merge
  mid = left + sz
  if mid > sz_data
    mid = sz_data
  .
  right = mid + sz
  if right > sz_data
    right = sz_data
  .
  l = left
  r = mid
  for i = left to right - 1
    if r = right or l < mid and tmp[l] < tmp[r]
      data[i] = tmp[l]
      l += 1
    else
      data[i] = tmp[r]
      r += 1
    .
  .
.
subr sort
  sz_data = len data[]
  len tmp[] sz_data
  sz = 1
  while sz < sz_data
    swap tmp[] data[]
    left = 0
    while left < sz_data
      call merge
      left += sz + sz
    .
    sz += sz
  .
.
data[] = [ 29 4 72 44 55 26 27 77 92 5 ]
call sort
print data[]


class
	MERGE_SORT [G -> COMPARABLE]

create
	sort

feature

	sort (ar: ARRAY [G])
			-- Sorted array in ascending order.
		require
			ar_not_empty: not ar.is_empty
		do
			create sorted_array.make_empty
			mergesort (ar, 1, ar.count)
			sorted_array := ar
		ensure
			sorted_array_not_empty: not sorted_array.is_empty
			sorted: is_sorted (sorted_array, 1, sorted_array.count)
		end

	sorted_array: ARRAY [G]

feature {NONE}

	mergesort (ar: ARRAY [G]; l, r: INTEGER)
			-- Sorting part of mergesort.
		local
			m: INTEGER
		do
			if l < r then
				m := (l + r) // 2
				mergesort (ar, l, m)
				mergesort (ar, m + 1, r)
				merge (ar, l, m, r)
			end
		end

	merge (ar: ARRAY [G]; l, m, r: INTEGER)
			-- Merge part of mergesort.
		require
			positive_index_l: l >= 1
			positive_index_m: m >= 1
			positive_index_r: r >= 1
			ar_not_empty: not ar.is_empty
		local
			merged: ARRAY [G]
			h, i, j, k: INTEGER
		do
			i := l
			j := m + 1
			k := l
			create merged.make_filled (ar [1], 1, ar.count)
			from
			until
				i > m or j > r
			loop
				if ar.item (i) <= ar.item (j) then
					merged.force (ar.item (i), k)
					i := i + 1
				elseif ar.item (i) > ar.item (j) then
					merged.force (ar.item (j), k)
					j := j + 1
				end
				k := k + 1
			end
			if i > m then
				from
					h := j
				until
					h > r
				loop
					merged.force (ar.item (h), k + h - j)
					h := h + 1
				end
			elseif j > m then
				from
					h := i
				until
					h > m
				loop
					merged.force (ar.item (h), k + h - i)
					h := h + 1
				end
			end
			from
				h := l
			until
				h > r
			loop
				ar.item (h) := merged.item (h)
				h := h + 1
			end
		ensure
			is_partially_sorted: is_sorted (ar, l, r)
		end

	is_sorted (ar: ARRAY [G]; l, r: INTEGER): BOOLEAN
			-- Is 'ar' sorted in ascending order?
		require
			ar_not_empty: not ar.is_empty
			l_in_range: l >= 1
			r_in_range: r <= ar.count
		local
			i: INTEGER
		do
			Result := True
			from
				i := l
			until
				i = r
			loop
				if ar [i] > ar [i + 1] then
					Result := False
				end
				i := i + 1
			end
		end

end


fcn insertionSort(list){
   sink:=List();
   foreach x in (list){
      if(False==(n:=sink.filter1n('>(x)))) sink.append(x); // x>all items in sink
      else sink.insert(n,x);
   }
   sink.close();
}


#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <vector>

// This only works for random access iterators
template <typename iterator>
void cocktail_shaker_sort(iterator begin, iterator end) {
    if (begin == end)
        return;
    for (--end; begin < end; ) {
        iterator new_begin = end;
        iterator new_end = begin;
        for (iterator i = begin; i < end; ++i) {
            iterator j = i + 1;
            if (*j < *i) {
                std::iter_swap(i, j);
                new_end = i;
            }
        }
        end = new_end;
        for (iterator i = end; i > begin; --i) {
            iterator j = i - 1;
            if (*i < *j) {
                std::iter_swap(i, j);
                new_begin = i;
            }
        }
        begin = new_begin;
    }
}

template <typename iterator>
void print(iterator begin, iterator end) {
    if (begin == end)
        return;
    std::cout << *begin++;
    while (begin != end)
        std::cout << ' ' << *begin++;
    std::cout << '\n';
}

int main() {
    std::vector<int> v{5, 1, -6, 12, 3, 13, 2, 4, 0, 15};
    std::cout << "before: ";
    print(v.begin(), v.end());
    cocktail_shaker_sort(v.begin(), v.end());
    assert(std::is_sorted(v.begin(), v.end()));
    std::cout << "after: ";
    print(v.begin(), v.end());
    return 0;
}


Function SortThree( [Array] $data )
{
	if( $data[ 0 ] -gt $data[ 1 ] )
	{
		if( $data[ 0 ] -lt $data[ 2 ] )
		{
			$data = $data[ 1, 0, 2 ]
		} elseif ( $data[ 1 ] -lt $data[ 2 ] ){
			$data = $data[ 1, 2, 0 ]
		} else {
			$data = $data[ 2, 1, 0 ]
		}
	} else {
		if( $data[ 0 ] -gt $data[ 2 ] )
		{
			$data = $data[ 2, 0, 1 ]
		} elseif( $data[ 1 ] -gt $data[ 2 ] ) {
			$data = $data[ 0, 2, 1 ]
		}
	}
	$data
}

Function QuickSort( [Array] $data, $rand = ( New-Object Random ) )
{
	$datal = $data.length
	if( $datal -gt 3 )
	{
		[void] $datal--
		$median = ( SortThree $data[ 0, ( $rand.Next( 1, $datal - 1 ) ), -1 ] )[ 1 ]
		$lt = @()
		$eq = @()
		$gt = @()
		$data | ForEach-Object { if( $_ -lt $median ) { $lt += $_ } elseif( $_ -eq $median ) { $eq += $_ } else { $gt += $_ } }
		$lt = ( QuickSort $lt $rand )
		$gt = ( QuickSort $gt $rand )
		$data = @($lt) + $eq + $gt
	} elseif( $datal -eq 3 ) {
		$data = SortThree( $data )
	} elseif( $datal -eq 2 ) {
		if( $data[ 0 ] -gt $data[ 1 ] )
		{
			$data = $data[ 1, 0 ]
		}
	}
	$data
}

QuickSort 5,3,1,2,4
QuickSort 'e','c','a','b','d'
QuickSort 0.5,0.3,0.1,0.2,0.4
$l = 100; QuickSort ( 1..$l | ForEach-Object { $Rand = New-Object Random }{ $Rand.Next( 0, $l - 1 ) } )


:1→P
:L1→L2
:While P<dim(L2)
:If PP=1
:Then
:P+1→P
:Else
:If L2(P)≥L2(P-1)
:Then
:P+1→P
:Else
:L2(P)→Q
:L2(P-1)→L2(P)
:Q→L2(P-1)
:P-1→P
:End
:End
:End
:If L2(dim(L2))<L2(dim(L2)-1)
:Then
:L2(dim(L2))→Q
:L2(dim(L2)-1)→L2(dim(L2))
:Q→L2(dim(L2)-1)
:End
:DelVar P
:DelVar Q
:Return


RANDOMIZE                         !RAMDOMZE TIMER en QBASIC
DIM array(-5 TO 12)
CALL iniciarray(array())
PRINT "unsort: ";
CALL escritura(array())
CALL gnomeSort(array())
PRINT
PRINT "  sort: ";
CALL escritura(array())
END

SUB escritura (array())
    FOR i = LBOUND(array) TO UBOUND(array)
        PRINT array(i);
    NEXT i
    PRINT
END SUB

SUB gnomeSort (array())
    LET i = LBOUND(array) + 1
    LET j = i + 1
    DO WHILE i <= UBOUND(array)
       IF array(i - 1) <= array(i) THEN
          LET i = j
          LET j = j + 1
       ELSE
          LET T = array(i - 1)
          LET array(i - 1) = array(i)
          LET array(i) = T
          LET i = i - 1
          IF i = LBOUND(array) THEN
             LET i = j
             LET j = j + 1
          END IF
       END IF
    LOOP
END SUB

SUB iniciarray (array())
    FOR i = LBOUND(array) TO UBOUND(array)
        LET array(i) = (RND * 98) + 1
    NEXT i
END SUB


defmodule Sort do
  def merge_sort(list) when length(list) <= 1, do: list
  def merge_sort(list) do
    {left, right} = Enum.split(list, div(length(list), 2))
    :lists.merge( merge_sort(left), merge_sort(right))
  end
end


mergeSort(L) when length(L) == 1 -> L;
mergeSort(L) when length(L) > 1 ->
    {L1, L2} = lists:split(length(L) div 2, L),
    lists:merge(mergeSort(L1), mergeSort(L2)).


Sub cocktailShakerSort(bs() As Long)
    Dim As Long i, lb = Lbound(bs), ub = Ubound(bs) -1
    Dim As Long newlb, newub, tmp

    Do While lb <= ub
        newlb = ub
        newub = lb
        For i = lb To ub
            If bs(i) > bs(i + 1) Then
                tmp = bs(i): bs(i) = bs(i + 1): bs(i + 1) = tmp
                newub = i
            End If
        Next i
        ub = newub - 1
        For i = ub To lb Step -1
            If bs(i) > bs(i + 1) Then
                tmp = bs(i): bs(i) = bs(i + 1): bs(i + 1) = tmp
                newlb = i
            End If
        Next i
        lb = newlb + 1
    Loop
End Sub

'--- Programa Principal ---
Dim As Long i, array(-7 To 7)
Dim As Long a = Lbound(array), b = Ubound(array)

Randomize Timer
For i = a To b : array(i) = i : Next i
For i = a To b
    Swap array(i), array(Int(Rnd * (b - a + 1)) + a)
Next i

Print "unsort ";
For i = a To b : Print Using "####"; array(i); : Next i

cocktailShakerSort(array())  ' ordenar el array

Print !"\n  sort ";
For i = a To b : Print Using "####"; array(i); : Next i

Print !"\n--- terminado, pulsa RETURN---"
Sleep


package main

import (
    "fmt"
    "math/rand"
    "time"
)

// translation of pseudo-code
func cocktailShakerSort(a []int) {
    var begin = 0
    var end = len(a) - 2
    for begin <= end {
        newBegin := end
        newEnd := begin
        for i := begin; i <= end; i++ {
            if a[i] > a[i+1] {
                a[i+1], a[i] = a[i], a[i+1]
                newEnd = i
            }
        }
        end = newEnd - 1
        for i := end; i >= begin; i-- {
            if a[i] > a[i+1] {
                a[i+1], a[i] = a[i], a[i+1]
                newBegin = i
            }
        }
        begin = newBegin + 1
    }
}

// from the RC Cocktail sort task (no optimizations)
func cocktailSort(a []int) {
    last := len(a) - 1
    for {
        swapped := false
        for i := 0; i < last; i++ {
            if a[i] > a[i+1] {
                a[i], a[i+1] = a[i+1], a[i]
                swapped = true
            }
        }
        if !swapped {
            return
        }
        swapped = false
        for i := last - 1; i >= 0; i-- {
            if a[i] > a[i+1] {
                a[i], a[i+1] = a[i+1], a[i]
                swapped = true
            }
        }
        if !swapped {
            return
        }
    }
}

func main() {
    // First make sure the routines are working correctly.
    a := []int{21, 4, -9, 62, -7, 107, -62, 4, 0, -170}
    fmt.Println("Original array:", a)
    b := make([]int, len(a))
    copy(b, a) // as sorts mutate array in place
    cocktailSort(a)
    fmt.Println("Cocktail sort :", a)
    cocktailShakerSort(b)
    fmt.Println("C/Shaker sort :", b)

    // timing comparison code
    rand.Seed(time.Now().UnixNano())
    fmt.Println("\nRelative speed of the two sorts")
    fmt.Println("  N    x faster (CSS v CS)")
    fmt.Println("-----  -------------------")
    const runs = 10 // average over 10 runs say
    for _, n := range []int{1000, 2000, 4000, 8000, 10000, 20000} {
        sum := 0.0
        for i := 1; i <= runs; i++ {
            // get 'n' random numbers in range [0, 100,000]
            // with every other number being negated
            nums := make([]int, n)
            for i := 0; i < n; i++ {
                rn := rand.Intn(100000)
                if i%2 == 1 {
                    rn = -rn
                }
                nums[i] = rn
            }
            // copy the array
            nums2 := make([]int, n)
            copy(nums2, nums)

            start := time.Now()
            cocktailSort(nums)
            elapsed := time.Since(start)
            start2 := time.Now()
            cocktailShakerSort(nums2)
            elapsed2 := time.Since(start2)
            sum += float64(elapsed) / float64(elapsed2)
        }
        fmt.Printf(" %2dk      %0.3f\n", n/1000, sum/runs)
    }
}


qsort( [], [] ).
qsort( [H|U], S ) :- splitBy(H, U, L, R), qsort(L, SL), qsort(R, SR), append(SL, [H|SR], S).

% splitBy( H, U, LS, RS )
% True if LS = { L in U | L <= H }; RS = { R in U | R > H }
splitBy( _, [], [], []).
splitBy( H, [U|T], [U|LS], RS ) :- U =< H, splitBy(H, T, LS, RS).
splitBy( H, [U|T], LS, [U|RS] ) :- U  > H, splitBy(H, T, LS, RS).


PRINT "Gnome sort:"
  n = FUNC (_InitArray)
  PROC _ShowArray (n)
  PROC _Gnomesort (n)
  PROC _ShowArray (n)
PRINT

END

_Gnomesort PARAM (1)                   ' Gnome sort
  LOCAL (2)
  [email protected]=1
  [email protected]=2

  DO WHILE [email protected] < [email protected]
    IF @([email protected]) > @([email protected]) THEN
      PROC _Swap ([email protected], [email protected])
      [email protected] = [email protected] - 1
      IF [email protected] THEN
        CONTINUE
      ENDIF
    ENDIF
    [email protected] = [email protected]
    [email protected] = [email protected] + 1
  LOOP
RETURN

_Swap PARAM(2)                         ' Swap two array elements
  PUSH @([email protected])
  @([email protected]) = @([email protected])
  @([email protected]) = POP()
RETURN

_InitArray                             ' Init example array
  PUSH 4, 65, 2, -31, 0, 99, 2, 83, 782, 1

  FOR i = 0 TO 9
    @(i) = POP()
  NEXT

RETURN (i)

_ShowArray PARAM (1)                   ' Show array subroutine
  FOR i = 0 TO [email protected]
    PRINT @(i),
  NEXT

  PRINT
RETURN


gnome_sort "p" =

@NiX ^=lx -+                                                                     # iteration
   ~&r?\~& @lNXrX ->llx2rhPlrPCTxPrtPX~&lltPlhPrCXPrX ~&ll&& @llPrXh not "p",    # backward bubble
   ->~&rhPlCrtPX ~&r&& ~&lZ!| @bh "p"+-                                          # forward scan


Private Function gnomeSort(s As Variant) As Variant
    Dim i As Integer: i = 1
    Dim j As Integer: j = 2
    Dim tmp As Integer
    Do While i < UBound(s)
        If s(i) <= s(i + 1) Then
            i = j
            j = j + 1
        Else
            tmp = s(i)
            s(i) = s(i + 1)
            s(i + 1) = tmp
            i = i - 1
            If i = 0 Then
                i = j
                j = j + 1
            End If
        End If
    Loop
    gnomeSort = s
End Function

Public Sub main()
    Debug.Print Join(gnomeSort([{5, 3, 1, 7, 4, 1, 1, 20}]), ", ")
End Sub


function gnomeSort( a )
	dim i
	dim j
	i = 1
	j = 2
	do while i < ubound( a ) + 1
		if a(i-1) <= a(i) then
			i = j
			j = j + 1
		else
			swap a(i-1), a(i)
			i = i - 1
			if i = 0 then
				i = j
				j = j + 1
			end if
		end if
	loop
	gnomeSort = a
end function

sub swap( byref x, byref y )
	dim temp
	temp = x
	x = y
	y = temp
end sub


F combsort(&input)
   V gap = input.len
   V swaps = 1B
   L gap > 1 | swaps
      gap = max(1, Int(gap / 1.25))
      swaps = 0B
      L(i) 0 .< input.len - gap
         V j = i + gap
         I input[i] > input[j]
            swap(&input[i], &input[j])
            swaps = 1B

V y = [88, 18, 31, 44, 4, 0, 8, 81, 14, 78, 20, 76, 84, 33, 73, 75, 82, 5, 62, 70]
combsort(&y)
assert(y == sorted(y))
print(y)


PROGRAM MERGESORT_DEMO

! Example of merge sort usage.

CONST SIZE%=100,S1%=50

DIM DTA%[SIZE%],FH%[S1%],STACK%[20,2]

PROCEDURE MERGE(START%,MIDDLE%,ENDS%)

LOCAL FHSIZE%

  FHSIZE%=MIDDLE%-START%+1

  FOR I%=0 TO FHSIZE%-1 DO
     FH%[I%]=DTA%[START%+I%]
  END FOR

  I%=0
  J%=MIDDLE%+1
  K%=START%

  REPEAT
    IF FH%[I%]<=DTA%[J%] THEN
        DTA%[K%]=FH%[I%]
        I%=I%+1
        K%=K%+1
      ELSE
        DTA%[K%]=DTA%[J%]
        J%=J%+1
        K%=K%+1
    END IF
  UNTIL I%=FHSIZE% OR J%>ENDS%

  WHILE I%<FHSIZE% DO
     DTA%[K%]=FH%[I%]
     I%=I%+1
     K%=K%+1
  END WHILE

END PROCEDURE

PROCEDURE MERGE_SORT(LEV->LEV)

! *****************************************************************
! This procedure Merge Sorts the chunk of DTA% bounded by
! Start% & Ends%.
! *****************************************************************

   LOCAL MIDDLE%

   IF ENDS%=START% THEN LEV=LEV-1 EXIT PROCEDURE END IF

   IF ENDS%-START%=1 THEN
      IF DTA%[ENDS%]<DTA%[START%] THEN
         SWAP(DTA%[START%],DTA%[ENDS%])
      END IF
      LEV=LEV-1
      EXIT PROCEDURE
   END IF

   MIDDLE%=START%+(ENDS%-START%)/2

   STACK%[LEV,0]=START%  STACK%[LEV,1]=ENDS%  STACK%[LEV,2]=MIDDLE%
   START%=START%  ENDS%=MIDDLE%
   MERGE_SORT(LEV+1->LEV)
   START%=STACK%[LEV,0]  ENDS%=STACK%[LEV,1]  MIDDLE%=STACK%[LEV,2]

   STACK%[LEV,0]=START%  STACK%[LEV,1]=ENDS%  STACK%[LEV,2]=MIDDLE%
   START%=MIDDLE%+1  ENDS%=ENDS%
   MERGE_SORT(LEV+1->LEV)
   START%=STACK%[LEV,0]  ENDS%=STACK%[LEV,1]  MIDDLE%=STACK%[LEV,2]

   MERGE(START%,MIDDLE%,ENDS%)

   LEV=LEV-1
END PROCEDURE

BEGIN
  FOR I%=1 TO SIZE% DO
     DTA%[I%]=RND(1)*10000
  END FOR

  START%=1  ENDS%=SIZE%
  MERGE_SORT(0->LEV)

  FOR I%=1 TO SIZE% DO
     WRITE("#####";DTA%[I%];)
  END FOR
  PRINT
END PROGRAM


function merge(sequence left, sequence right)
    sequence result
    result = {}
    while length(left) > 0 and length(right) > 0 do
        if compare(left[1], right[1]) <= 0 then
            result = append(result, left[1])
            left = left[2..$]
        else
            result = append(result, right[1])
            right = right[2..$]
        end if
    end while
    return result & left & right
end function

function mergesort(sequence m)
    sequence left, right
    integer middle
    if length(m) <= 1 then
        return m
    else
        middle = floor(length(m)/2)
        left = mergesort(m[1..middle])
        right = mergesort(m[middle+1..$])
        if compare(left[$], right[1]) <= 0 then
            return left & right
        elsif compare(right[$], left[1]) <= 0 then
            return right & left
        else
            return merge(left, right)
        end if
    end if
end function

constant s = rand(repeat(1000,10))
? s
? mergesort(s)


class CocktailSort {
    static void main(String[] args) {
        Integer[] array = [ 5, 1, -6, 12, 3, 13, 2, 4, 0, 15 ]
        println("before: " + Arrays.toString(array))
        cocktailSort(array)
        println("after: " + Arrays.toString(array))
    }

    // Sorts an array of elements that implement the Comparable interface
    static void cocktailSort(Object[] array) {
        int begin = 0
        int end = array.length
        if (end == 0) {
            return
        }
        for (--end; begin < end; ) {
            int new_begin = end
            int new_end = begin
            for (int i = begin; i < end; ++i) {
                Comparable c1 = (Comparable)array[i]
                Comparable c2 = (Comparable)array[i + 1]
                if (c1 > c2) {
                    swap(array, i, i + 1)
                    new_end = i
                }
            }
            end = new_end
            for (int i = end; i > begin; --i) {
                Comparable c1 = (Comparable)array[i - 1]
                Comparable c2 = (Comparable)array[i]
                if (c1 > c2) {
                    swap(array, i, i - 1)
                    new_begin = i
                }
            }
            begin = new_begin
        }
    }

    private static void swap(Object[] array, int i, int j) {
        Object tmp = array[i]
        array[i] = array[j]
        array[j] = tmp
    }
}


import java.util.*;

public class CocktailSort {
    public static void main(String[] args) {
        Integer[] array = new Integer[]{ 5, 1, -6, 12, 3, 13, 2, 4, 0, 15 };
        System.out.println("before: " + Arrays.toString(array));
        cocktailSort(array);
        System.out.println("after: " + Arrays.toString(array));
    }

    // Sorts an array of elements that implement the Comparable interface
    public static void cocktailSort(Object[] array) {
        int begin = 0;
        int end = array.length;
        if (end == 0)
            return;
        for (--end; begin < end; ) {
            int new_begin = end;
            int new_end = begin;
            for (int i = begin; i < end; ++i) {
                Comparable c1 = (Comparable)array[i];
                Comparable c2 = (Comparable)array[i + 1];
                if (c1.compareTo(c2) > 0) {
                    swap(array, i, i + 1);
                    new_end = i;
                }
            }
            end = new_end;
            for (int i = end; i > begin; --i) {
                Comparable c1 = (Comparable)array[i - 1];
                Comparable c2 = (Comparable)array[i];
                if (c1.compareTo(c2) > 0) {
                    swap(array, i, i - 1);
                    new_begin = i;
                }
            }
            begin = new_begin;
        }
    }

    private static void swap(Object[] array, int i, int j) {
        Object tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
}


Procedure qSort(Array a(1), firstIndex, lastIndex)
  Protected  low, high, pivotValue

  low = firstIndex
  high = lastIndex
  pivotValue = a((firstIndex + lastIndex) / 2)

  Repeat

    While a(low) < pivotValue
      low + 1
    Wend

    While a(high) > pivotValue
      high - 1
    Wend

    If low <= high
      Swap a(low), a(high)
      low + 1
      high - 1
    EndIf

  Until low > high

  If firstIndex < high
    qSort(a(), firstIndex, high)
  EndIf

  If low < lastIndex
    qSort(a(), low, lastIndex)
  EndIf
EndProcedure

Procedure quickSort(Array a(1))
  qSort(a(),0,ArraySize(a()))
EndProcedure


fn main() {
    mut a := [170, 45, 75, -90, -802, 24, 2, 66]
    println("before: $a")
    gnome_sort(mut a)
    println("after: $a")
}

fn gnome_sort(mut a []int) {
    for i, j := 1, 2; i < a.len; {
        if a[i-1] > a[i] {
            a[i-1], a[i] = a[i], a[i-1]
            i--
            if i > 0 {
                continue
            }
        }
        i = j
        j++
    }
}


var gnomeSort = Fn.new { |a, asc|
    var size = a.count
    var i = 1
    var j = 2
    while (i < size) {
        if ((asc && a[i-1] <= a[i]) || (!asc && a[i-1] >= a[i])) {
            i = j
            j = j + 1
        } else {
            var t = a[i-1]
            a[i-1] = a[i]
            a[i] = t
            i = i - 1
            if (i == 0) {
                i = j
                j = j + 1
            }
        }
    }
}

var as = [ [4, 65, 2, -31, 0, 99, 2, 83, 782, 1], [7, 5, 2, 6, 1, 4, 2, 6, 3] ]

for (asc in [true, false]) {
    System.print("Sorting in %(asc ? "ascending" : "descending") order:\n")
    for (a in as) {
        var b = (asc) ? a : a.toList
        System.print("Before: %(b)")
        gnomeSort.call(b, asc)
        System.print("After : %(b)")
        System.print()
    }
}


*        Comb sort                 23/06/2016
COMBSORT CSECT
         USING  COMBSORT,R13       base register
         B      72(R15)            skip savearea
         DC     17F'0'             savearea
         STM    R14,R12,12(R13)    prolog
         ST     R13,4(R15)         "
         ST     R15,8(R13)         "
         LR     R13,R15            "
         L      R2,N               n
         BCTR   R2,0               n-1
         ST     R2,GAP             gap=n-1
         DO     UNTIL=(CLC,GAP,EQ,=F'1',AND,CLI,SWAPS,EQ,X'00') repeat
         L      R4,GAP               gap                             |
         MH     R4,=H'100'           gap*100                         |
         SRDA   R4,32                .                               |
         D      R4,=F'125'           /125                            |
         ST     R5,GAP               gap=int(gap/1.25)               |
         IF     CLC,GAP,LT,=F'1'     if gap<1 then  -----------+     |
         MVC    GAP,=F'1'              gap=1                   |     |
         ENDIF  ,                    end if  <-----------------+     |
         MVI    SWAPS,X'00'          swaps=false                     |
         LA     RI,1                 i=1                             |
         DO     UNTIL=(C,R3,GT,N)    do i=1 by 1 until i+gap>n  ---+ |
         LR     R7,RI                  i                           | |
         SLA    R7,2                   .                           | |
         LA     R7,A-4(R7)             [email protected](i)                    | |
         LR     R8,RI                  i                           | |
         A      R8,GAP                 i+gap                       | |
         SLA    R8,2                   .                           | |
         LA     R8,A-4(R8)             [email protected](i+gap)                | |
         L      R2,0(R7)               temp=a(i)                   | |
         IF     C,R2,GT,0(R8)          if a(i)>a(i+gap) then  ---+ | |
         MVC    0(4,R7),0(R8)            a(i)=a(i+gap)           | | |
         ST     R2,0(R8)                 a(i+gap)=temp           | | |
         MVI    SWAPS,X'01'              swaps=true              | | |
         ENDIF  ,                      end if  <-----------------+ | |
         LA     RI,1(RI)               i=i+1                       | |
         LR     R3,RI                  i                           | |
         A      R3,GAP                 i+gap                       | |
         ENDDO  ,                    end do  <---------------------+ |
         ENDDO  ,                  until gap=1 and not swaps  <------+
         LA     R3,PG              pgi=0
         LA     RI,1               i=1
         DO     WHILE=(C,RI,LE,N)  do i=1 to n  -------+
         LR     R1,RI                i                 |
         SLA    R1,2                 .                 |
         L      R2,A-4(R1)           a(i)              |
         XDECO  R2,XDEC              edit a(i)         |
         MVC    0(4,R3),XDEC+8       output a(i)       |
         LA     R3,4(R3)             pgi=pgi+4         |
         LA     RI,1(RI)             i=i+1             |
         ENDDO  ,                  end do  <-----------+
         XPRNT  PG,L'PG            print buffer
         L      R13,4(0,R13)       epilog
         LM     R14,R12,12(R13)    "
         XR     R15,R15            "
         BR     R14                exit
A     DC F'4',F'65',F'2',F'-31',F'0',F'99',F'2',F'83',F'782',F'1'
      DC F'45',F'82',F'69',F'82',F'104',F'58',F'88',F'112',F'89',F'74'
N        DC     A((N-A)/L'A)       number of items of a
GAP      DS     F                  gap
SWAPS    DS     X                  flag for swaps
PG       DS     CL80               output buffer
XDEC     DS     CL12               temp for edit
         YREGS
RI       EQU    6                  i
         END    COMBSORT