import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class Merge{
    public static <E extends Comparable<? super E>> List<E> mergeSort(List<E> m){
        if(m.size() <= 1) return m;

        int middle = m.size() / 2;
        List<E> left = m.subList(0, middle);
        List<E> right = m.subList(middle, m.size());

        right = mergeSort(right);
        left = mergeSort(left);
        List<E> result = merge(left, right);

        return result;
    }

    public static <E extends Comparable<? super E>> List<E> merge(List<E> left, List<E> right){
        List<E> result = new ArrayList<E>();
        Iterator<E> it1 = left.iterator();
        Iterator<E> it2 = right.iterator();

	E x = it1.next();
	E y = it2.next();
        while (true){
            //change the direction of this comparison to change the direction of the sort
            if(x.compareTo(y) <= 0){
		result.add(x);
		if(it1.hasNext()){
		    x = it1.next();
		}else{
		    result.add(y);
		    while(it2.hasNext()){
			result.add(it2.next());
		    }
		    break;
		}
	    }else{
		result.add(y);
		if(it2.hasNext()){
		    y = it2.next();
		}else{
		    result.add(x);
		    while (it1.hasNext()){
			result.add(it1.next());
		    }
		    break;
		}
	    }
        }
        return result;
    }
}


(defun counting-sort (sequence &optional (min (reduce #'min sequence))
                                         (max (reduce #'max sequence)))
  (let ((i 0)
        (counts (make-array (1+ (- max min)) :initial-element 0
                                             :element-type `(integer 0 ,(length sequence)))))
    (declare (dynamic-extent counts))
    (map nil (lambda (n) (incf (aref counts (- n min)))) sequence)
    (map-into sequence (lambda ()
                         (do () ((plusp (aref counts i)))
                           (incf i))
                         (decf (aref counts i))
                         (+ i min)))))


import std.stdio, std.algorithm;

void countingSort(int[] array, in size_t min, in size_t max)
pure nothrow {
    auto count = new int[max - min + 1];
    foreach (number; array)
        count[number - min]++;

    size_t z = 0;
    foreach (i; min .. max + 1)
        while (count[i - min] > 0) {
            array[z] = i;
            z++;
            count[i - min]--;
        }
}

void main() {
    auto data = [9, 7, 10, 2, 9, 7, 4, 3, 10, 2, 7, 10, 2, 1, 3, 8,
                 7, 3, 9, 5, 8, 5, 1, 6, 3, 7, 5, 4, 6, 9, 9, 6, 6,
                 10, 2, 4, 5, 2, 8, 2, 2, 5, 2, 9, 3, 3, 5, 7, 8, 4];

    int dataMin = reduce!min(data);
    int dataMax = reduce!max(data);
    countingSort(data, dataMin, dataMax);
    assert(isSorted(data));
}


# Project : Sorting algorithms/Quicksort

test = [4, 65, 2, -31, 0, 99, 2, 83, 782, 1]
see "before sort:" + nl
showarray(test)
quicksort(test, 1, 10)
see "after sort:" + nl
showarray(test)

func quicksort(a, s, n)
       if n < 2
          return
       ok
       t = s + n - 1
       l = s
       r = t
       p = a[floor((l + r) / 2)]
       while l <= r
               while a[l] < p
                       l = l + 1
               end
               while a[r] > p
                       r = r - 1
               end
               if l <= r
                  temp = a[l]
                  a[l] = a[r]
                  a[r] = temp
                  l = l + 1
                  r = r - 1
              ok
       end
       if s < r
          quicksort(a, s, r - s + 1)
       ok
       if l < t
         quicksort(a, l, t - l + 1 )
       ok

func showarray(vect)
        svect = ""
        for n = 1 to len(vect)
              svect = svect + vect[n] + " "
        next
        svect = left(svect, len(svect) - 1)
        see svect + nl


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

           MOVE WC-SIZE TO WC-GAP.

           PERFORM E-COMB UNTIL WC-GAP = 1 AND FINISHED.

           DISPLAY "SORT FINISHED".

       C-999.
           EXIT.

       E-COMB SECTION.
       E-000.
           IF WC-GAP > 1
              DIVIDE WC-GAP BY 1.3 GIVING WC-GAP
              IF WC-GAP = 9 OR 10
                 MOVE 11 TO WC-GAP.

           MOVE 1   TO WC-SUB-1.
           MOVE "Y" TO WF-FINISHED.

           PERFORM F-SCAN UNTIL WC-SUB-1 + WC-GAP > WC-SIZE.

       E-999.
           EXIT.

       F-SCAN SECTION.
       F-000.
           ADD WC-SUB-1 WC-GAP GIVING WC-SUB-2.
           IF WB-ENTRY(WC-SUB-1) > WB-ENTRY(WC-SUB-2)
              MOVE WB-ENTRY(WC-SUB-1) TO WC-TEMP
              MOVE WB-ENTRY(WC-SUB-2) TO WB-ENTRY(WC-SUB-1)
              MOVE WC-TEMP            TO WB-ENTRY(WC-SUB-2)
              MOVE "N"                TO WF-FINISHED.

           ADD 1 TO WC-SUB-1.

       F-999.
           EXIT.


(defparameter *shrink* 1.3)

(defun comb-sort (input)
  (loop with input-size = (length input)
        with gap = input-size
        with swapped
        do (when (> gap 1)
             (setf gap (floor gap *shrink*)))
           (setf swapped nil)
           (loop for lo from 0
                 for hi from gap below input-size
                 when (> (aref input lo) (aref input hi))
                   do (rotatef (aref input lo) (aref input hi))
                      (setf swapped t))
        while (or (> gap 1) swapped)
        finally (return input)))


function merge(left, right, arr) {
  var a = 0;

  while (left.length && right.length) {
    arr[a++] = (right[0] < left[0]) ? right.shift() : left.shift();
  }
  while (left.length) {
    arr[a++] = left.shift();
  }
  while (right.length) {
    arr[a++] = right.shift();
  }
}

function mergeSort(arr) {
  var len = arr.length;

  if (len === 1) { return; }

  var mid = Math.floor(len / 2),
      left = arr.slice(0, mid),
      right = arr.slice(mid);

  mergeSort(left);
  mergeSort(right);
  merge(left, right, arr);
}

var arr = [1, 5, 2, 7, 3, 9, 4, 6, 8];
mergeSort(arr); // arr will now: 1, 2, 3, 4, 5, 6, 7, 8, 9

// here is improved faster version, also often faster than QuickSort!

function mergeSort2(a) {
  if (a.length <= 1) return
  const mid = Math.floor(a.length / 2), left = a.slice(0, mid), right = a.slice(mid)
  mergeSort2(left)
  mergeSort2(right)
  let ia = 0, il = 0, ir = 0
  while (il < left.length && ir < right.length)
    a[ia++] = left[il] < right[ir] ? left[il++] : right[ir++]
  while (il < left.length)
    a[ia++] = left[il++]
  while (ir < right.length)
    a[ia++] = right[ir++]
}


def countingSort(array, min, max) {
    def counts := ([0] * (max - min + 1)).diverge()
    for elem in array {
        counts[elem - min] += 1
    }
    var i := -1
    for offset => count in counts {
        def elem := min + offset
        for _ in 1..count {
            array[i += 1] := elem
        }
    }
}


class Array
  def quick_sort
    return self if length <= 1
    pivot = self[0]
    less, greatereq = self[1..-1].partition { |x| x < pivot }
    less.quick_sort + [pivot] + greatereq.quick_sort
  end
end


import std.stdio, std.algorithm;

void combSort(T)(T[] input) pure nothrow @safe @nogc {
    int gap = input.length;
    bool swaps = true;

    while (gap > 1 || swaps) {
        gap = max(1, cast(int)(gap / 1.2473));
        swaps = false;
        foreach (immutable i; 0 .. input.length - gap)
            if (input[i] > input[i + gap]) {
                input[i].swap(input[i + gap]);
                swaps = true;
            }
    }
}

void main() {
    auto data = [28, 44, 46, 24, 19, 2, 17, 11, 25, 4];
    data.combSort;
    data.writeln;
}


program Comb_sort;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Types;

type
  THelperIntegerDynArray = record helper for TIntegerDynArray
  public
    procedure CombSort;
    procedure FillRange(Count: integer);
    procedure Shuffle;
    function ToString: string;
  end;

{ THelperIntegerDynArray }
procedure THelperIntegerDynArray.CombSort;
var
  i, gap, temp: integer;
  swapped: boolean;
begin
  gap := length(self);
  swapped := true;
  while (gap > 1) or swapped do
  begin
    gap := trunc(gap / 1.3);
    if (gap < 1) then
      gap := 1;
    swapped := false;
    for i := 0 to length(self) - gap - 1 do
      if self[i] > self[i + gap] then
      begin
        temp := self[i];
        self[i] := self[i + gap];
        self[i + gap] := temp;
        swapped := true;
      end;
  end;
end;

procedure THelperIntegerDynArray.FillRange(Count: integer);
var
  i: Integer;
begin
  SetLength(self, Count);
  for i := 0 to Count - 1 do
    Self[i] := i;
end;

procedure THelperIntegerDynArray.Shuffle;
var
  i, j, tmp: integer;
  count: integer;
begin
  Randomize;
  count := Length(self);
  for i := 0 to count - 1 do
  begin
    j := i + Random(count - i);
    tmp := self[i];
    self[i] := self[j];
    self[j] := tmp;
  end;
end;

function THelperIntegerDynArray.ToString: string;
var
  value: Integer;
begin
  Result := '';
  for value in self do
  begin
    Result := Result + ' ' + Format('%4d', [value]);
  end;
  Result := '[' + Result.Trim + ']';
end;

var
  data: TIntegerDynArray;

begin
  data.FillRange(10);
  data.Shuffle;
  writeln('The data before sorting:');
  Writeln(data.ToString, #10);

  data.CombSort;

  writeln('The data after sorting:');
  Writeln(data.ToString, #10);

  Readln;
end.


# Input: [x,y] -- the two arrays to be merged
# If x and y are sorted as by "sort", then the result will also be sorted:
def merge:
  def m:  # state: [x, y, array]  (array being the answer)
    .[0] as $x
    | .[1] as $y
    | if   0 == ($x|length) then .[2] + $y
      elif 0 == ($y|length) then .[2] + $x
      else
        (if $x[0] <= $y[0] then [$x[1:], $y,     .[2] + [$x[0] ]]
         else                   [$x,     $y[1:], .[2] + [$y[0] ]]
         end) | m
      end;
   [.[0], .[1], []] | m;

def merge_sort:
  if length <= 1 then .
  else
    (length/2 |floor) as $len
    | . as $in
    | [ ($in[0:$len] | merge_sort), ($in[$len:] | merge_sort) ] | merge
  end;


function mergesort(arr::Vector)
    if length(arr) ≤ 1 return arr end
    mid = length(arr) ÷ 2
    lpart = mergesort(arr[1:mid])
    rpart = mergesort(arr[mid+1:end])
    rst = similar(arr)
    i = ri = li = 1
    @inbounds while li ≤ length(lpart) && ri ≤ length(rpart)
        if lpart[li] ≤ rpart[ri]
            rst[i] = lpart[li]
            li += 1
        else
            rst[i] = rpart[ri]
            ri += 1
        end
        i += 1
    end
    if li ≤ length(lpart)
        copy!(rst, i, lpart, li)
    else
        copy!(rst, i, rpart, ri)
    end
    return rst
end

v = rand(-10:10, 10)
println("# unordered: $v\n -> ordered: ", mergesort(v))


class
	COUNTING_SORT

feature

	sort (ar: ARRAY [INTEGER]; min, max: INTEGER): ARRAY [INTEGER]
			-- Sorted Array in ascending order.
		require
			ar_not_void: ar /= Void
			lowest_index_zero: ar.lower = 0
		local
			count: ARRAY [INTEGER]
			i, j, z: INTEGER
		do
			create Result.make_empty
			Result.deep_copy (ar)
			create count.make_filled (0, 0, max - min)
			from
				i := 0
			until
				i = Result.count
			loop
				count [Result [i] - min] := count [Result [i] - min] + 1
				i := i + 1
			end
			z := 0
			from
				i := min
			until
				i > max
			loop
				from
					j := 0
				until
					j = count [i - min]
				loop
					Result [z] := i
					z := z + 1
					j := j + 1
				end
				i := i + 1
			end
		ensure
			Result_is_sorted: is_sorted (Result)
		end

feature {NONE}

	is_sorted (ar: ARRAY [INTEGER]): BOOLEAN
			--- Is 'ar' sorted in ascending order?
		require
			ar_not_empty: ar.is_empty = False
		local
			i: INTEGER
		do
			Result := True
			from
				i := ar.lower
			until
				i = ar.upper
			loop
				if ar [i] > ar [i + 1] then
					Result := False
				end
				i := i + 1
			end
		end

end


import extensions;
import system'routines;

extension op
{
    countingSort()
        = self.clone().countingSort(self.MinimalMember, self.MaximalMember);

    countingSort(int min, int max)
    {
        int[] count := new int[](max - min + 1);
        int z := 0;

        count.populate:(int i => 0);

        for(int i := 0, i < self.Length, i += 1) { count[self[i] - min] := count[self[i] - min] + 1 };

        for(int i := min, i <= max, i += 1)
        {
            while (count[i - min] > 0)
            {
                self[z] := i;
                z += 1;

                count[i - min] := count[i - min] - 1
            }
        }
    }
}

public program()
{
    var list := new Range(0, 10).selectBy:(i => randomGenerator.eval(10)).toArray();

    console.printLine("before:", list.asEnumerable());
    console.printLine("after :", list.countingSort().asEnumerable())
}


' -------------------------------
' quick sort
' -------------------------------
size = 50
dim s(size)			' array to sort
for i = 1 to size		' fill it with some random numbers
 s(i) = rnd(0) * 100
next i

lft  = 1
rht  = size

[qSort]
  lftHold = lft
  rhtHold = rht
  pivot   = s(lft)
  while lft < rht
    while (s(rht) >= pivot) and (lft < rht) : rht = rht - 1 :wend
    if lft <> rht then
      s(lft) = s(rht)
      lft    = lft + 1
    end if
    while (s(lft) <= pivot) and (lft < rht) : lft = lft + 1 :wend
    if lft <> rht then
      s(rht) = s(lft)
      rht    = rht - 1
    end if
  wend

  s(lft) = pivot
  pivot  = lft
  lft    = lftHold
  rht    = rhtHold
  if lft < pivot then
    rht = pivot - 1
    goto [qSort]
  end if
 if rht > pivot then
    lft = pivot + 1
    goto [qSort]
 end if

for i = 1 to size
 print i;"-->";s(i)
next i


class
	COMB_SORT [G -> COMPARABLE]

feature

	combsort (ar: ARRAY [G]): ARRAY [G]
			-- Sorted array in ascending order.
		require
			array_not_void: ar /= Void
		local
			gap, i: INTEGER
			swap: G
			swapped: BOOLEAN
			shrink: REAL_64
		do
			create Result.make_empty
			Result.deep_copy (ar)
			gap := Result.count
			from
			until
				gap = 1 and swapped = False
			loop
				from
					i := Result.lower
					swapped := False
				until
					i + gap > Result.count
				loop
					if Result [i] > Result [i + gap] then
						swap := Result [i]
						Result [i] := Result [i + gap]
						Result [i + gap] := swap
						swapped := True
					end
					i := i + 1
				end
				shrink := gap / 1.3
				gap := shrink.floor
				if gap < 1 then
					gap := 1
				end
			end
		ensure
			Result_is_set: Result /= Void
			Result_is_sorted: is_sorted (Result)
		end

feature {NONE}

	is_sorted (ar: ARRAY [G]): BOOLEAN
			--- Is 'ar' sorted in ascending order?
		require
			ar_not_empty: ar.is_empty = False
		local
			i: INTEGER
		do
			Result := True
			from
				i := ar.lower
			until
				i = ar.upper
			loop
				if ar [i] > ar [i + 1] then
					Result := False
				end
				i := i + 1
			end
		end

end


import extensions;
import system'math;
import system'routines;

extension op
{
    combSort()
    {
        var list := self.clone();

        real gap := list.Length;
        bool swaps := true;
        while (gap > 1 || swaps)
        {
            gap /= 1.247330950103979r;
            if (gap<1) { gap := 1 };

            int i := 0;
            swaps := false;
            while (i + gap.RoundedInt < list.Length)
            {
                int igap := i + gap.RoundedInt;
                if (list[i] > list[igap])
                {
                    list.exchange(i,igap);
                    swaps := true
                };
                i += 1
            }
        };

        ^ list
    }
}

public program()
{
    var list := new int[]{3, 5, 1, 9, 7, 6, 8, 2, 4 };

    console.printLine("before:", list.asEnumerable());
    console.printLine("after :", list.combSort().asEnumerable())
}


fun mergeSort(list: List<Int>): List<Int> {
    if (list.size <= 1) {
        return list
    }

    val left = mutableListOf<Int>()
    val right = mutableListOf<Int>()

    val middle = list.size / 2
    list.forEachIndexed { index, number ->
        if (index < middle) {
            left.add(number)
        } else {
            right.add(number)
        }
    }

    fun merge(left: List<Int>, right: List<Int>): List<Int> = mutableListOf<Int>().apply {
        var indexLeft = 0
        var indexRight = 0

        while (indexLeft < left.size && indexRight < right.size) {
            if (left[indexLeft] <= right[indexRight]) {
                add(left[indexLeft])
                indexLeft++
            } else {
                add(right[indexRight])
                indexRight++
            }
        }

        while (indexLeft < left.size) {
            add(left[indexLeft])
            indexLeft++
        }

        while (indexRight < right.size) {
            add(right[indexRight])
            indexRight++
        }
    }

    return merge(mergeSort(left), mergeSort(right))
}

fun main(args: Array<String>) {
    val numbers = listOf(5, 2, 3, 17, 12, 1, 8, 3, 4, 9, 7)
    println("Unsorted: $numbers")
    println("Sorted: ${mergeSort(numbers)}")
}


{def alt
 {lambda {:list}
  {if {A.empty? :list}
   then {A.new}
   else {A.addfirst! {A.first :list}
                     {alt {A.rest {A.rest :list}}}} }}}
-> alt

{def merge
 {lambda {:l1 :l2}
  {if {A.empty? :l2}
   then :l1
   else {if {< {A.first :l1} {A.first :l2}}
   then {A.addfirst! {A.first :l1} {merge :l2 {A.rest :l1}}}
   else {A.addfirst! {A.first :l2} {merge :l1 {A.rest :l2}}} }}}}
-> merge

{def mergesort
 {lambda {:list}
  {if {A.empty? {A.rest :list}}
   then :list
   else {merge {mergesort {alt :list}}
               {mergesort {alt {A.rest :list}}}} }}}
-> mergesort

{mergesort {A.new 8 1 5 3 9 0 2 7 6 4}}
-> [0,1,2,3,4,5,6,7,8,9]


defmodule Sort do
  def counting_sort([]), do: []
  def counting_sort(list) do
    {min, max} = Enum.min_max(list)
    count = Tuple.duplicate(0, max - min + 1)
    counted = Enum.reduce(list, count, fn x,acc ->
      i = x - min
      put_elem(acc, i, elem(acc, i) + 1)
    end)
    Enum.flat_map(min..max, &List.duplicate(&1, elem(counted, &1 - min)))
  end
end

IO.inspect Sort.counting_sort([1,-2,-3,2,1,-5,5,5,4,5,9])


module CountingSort
  implicit none

  interface counting_sort
     module procedure counting_sort_mm, counting_sort_a
  end interface

contains

  subroutine counting_sort_a(array)
    integer, dimension(:), intent(inout) :: array

    call counting_sort_mm(array, minval(array), maxval(array))

  end subroutine counting_sort_a

  subroutine counting_sort_mm(array, tmin, tmax)
    integer, dimension(:), intent(inout) :: array
    integer, intent(in) :: tmin, tmax

    integer, dimension(tmin:tmax) :: cnt
    integer :: i, z

    cnt = 0                   ! Initialize to zero to prevent false counts
    FORALL (I=1:size(array))  ! Not sure that this gives any benefit over a DO loop.
        cnt(array(i)) = cnt(array(i))+1
    END FORALL
!
!   ok - cnt contains the frequency of every value
!   let's unwind them into the original array
!
    z = 1
    do i = tmin, tmax
       do while ( cnt(i) > 0 )
          array(z) = i
          z = z + 1
          cnt(i) = cnt(i) - 1
       end do
    end do

  end subroutine counting_sort_mm

end module CountingSort


' FB 1.05.0 Win64

Function findMax(array() As Integer) As Integer
  Dim length As Integer = UBound(array) - LBound(array) + 1
  If length = 0 Then Return 0 '' say
  If length = 1 Then Return array(LBound(array))
  Dim max As Integer = LBound(array)
  For i As Integer = LBound(array) + 1 To UBound(array)
    If array(i) > max Then max = array(i)
  Next
  Return max
End Function

Function findMin(array() As Integer) As Integer
  Dim length As Integer = UBound(array) - LBound(array) + 1
  If length = 0 Then Return 0 '' say
  If length = 1 Then Return array(LBound(array))
  Dim min As Integer = LBound(array)
  For i As Integer = LBound(array) + 1 To UBound(array)
    If array(i) < min Then min = array(i)
  Next
  Return min
End Function

Sub countingSort(array() As Integer, min As Integer, max As Integer)
  Dim count(0 To max - min) As Integer '' all zero by default
  Dim As Integer number, z
  For i As Integer = LBound(array) To UBound(array)
    number = array(i)
    count(number - min) += 1
  Next
  z = LBound(array)
  For i As Integer = min To max
    While count(i - min) > 0
      array(z) = i
      z += 1
      count(i - min) -= 1
    Wend
  Next
End Sub

Sub printArray(array() As Integer)
  For i As Integer = LBound(array) To UBound(array)
    Print Using "####"; array(i);
  Next
  Print
End Sub

Dim array(1 To 10) As Integer = {4, 65, 2, -31, 0, 99, 2, 83, 782, 1} '' using BBC BASIC example array
Print "Unsorted : ";
printArray(array())
Dim max As Integer = findMax(array())
Dim min As Integer = findMin(array())
countingSort array(), min, max
Print "Sorted   : ";
printArray(array())
Print
Print "Press any key to quit"
Sleep


fn main() {
    println!("Sort numbers in descending order");
    let mut numbers = [4, 65, 2, -31, 0, 99, 2, 83, 782, 1];
    println!("Before: {:?}", numbers);

    quick_sort(&mut numbers, &|x,y| x > y);
    println!("After:  {:?}\n", numbers);

    println!("Sort strings alphabetically");
    let mut strings = ["beach", "hotel", "airplane", "car", "house", "art"];
    println!("Before: {:?}", strings);

    quick_sort(&mut strings, &|x,y| x < y);
    println!("After:  {:?}\n", strings);

    println!("Sort strings by length");
    println!("Before: {:?}", strings);

    quick_sort(&mut strings, &|x,y| x.len() < y.len());
    println!("After:  {:?}", strings);
}

fn quick_sort<T,F>(v: &mut [T], f: &F)
    where F: Fn(&T,&T) -> bool
{
    let len = v.len();
    if len >= 2 {
        let pivot_index = partition(v, f);
        quick_sort(&mut v[0..pivot_index], f);
        quick_sort(&mut v[pivot_index + 1..len], f);
    }
}

fn partition<T,F>(v: &mut [T], f: &F) -> usize
    where F: Fn(&T,&T) -> bool
{
    let len = v.len();
    let pivot_index = len / 2;
    let last_index = len - 1;

    v.swap(pivot_index, last_index);

    let mut store_index = 0;
    for i in 0..last_index {
        if f(&v[i], &v[last_index]) {
            v.swap(i, store_index);
            store_index += 1;
        }
    }

    v.swap(store_index, len - 1);
    store_index
}


defmodule Sort do
  def comb_sort([]), do: []
  def comb_sort(input) do
    comb_sort(List.to_tuple(input), length(input), 0) |> Tuple.to_list
  end

  defp comb_sort(output, 1, 0), do: output
  defp comb_sort(input, gap, _) do
    gap = max(trunc(gap / 1.25), 1)
    {output,swaps} = Enum.reduce(0..tuple_size(input)-gap-1, {input,0}, fn i,{acc,swap} ->
      if (x = elem(acc,i)) > (y = elem(acc,i+gap)) do
        {acc |> put_elem(i,y) |> put_elem(i+gap,x), 1}
      else
        {acc,swap}
      end
    end)
    comb_sort(output, gap, swaps)
  end
end

(for _ <- 1..20, do: :rand.uniform(20)) |> IO.inspect |> Sort.comb_sort |> IO.inspect


defer precedes
defer exchange

: gnomesort                            ( a n)
  swap >r 1                            ( n c)
  begin                                ( n c)
    over over >                        ( n c f)
  while                                ( n c)
    dup if                             ( n c)
      dup dup 1- over over [email protected] precedes
      if [email protected] exchange 1- else drop drop 1+ then
    else 1+ then                       ( n c)
  repeat drop drop r> drop             ( --)
;

: combsort                             ( a n --)
  dup begin                            ( a n g)
    10 13 */ tuck >r >r 0              ( a g 0)
    begin                              ( a g 0)
      over [email protected] <                        ( a g 0 f)
    while                              ( a g 0)
      rot >r over over [email protected] precedes     ( g 0 f)
      if over over [email protected] exchange then    ( g 0)
      r> rot 1+ rot 1+                 ( a g 0)
    repeat drop drop r> r>             ( a n g)
    dup 9 <                            ( a n g f)
  until drop gnomesort                 ( --)
;

create example
  8 93 69 52 50 79 33 52 19 77 , , , , , , , , , ,
 72 85 11 61 64 80 64 76 47 65 , , , , , , , , , ,
  13 47 23 40 87 45 2 48 22 69 , , , , , , , , , ,
  1 53 33 60 57 14 76 32 59 12 , , , , , , , , , ,
 74 38 39 22 87 28 37 93 71 88 , , , , , , , , , ,
 56 35 48 99 21 35 26 28 58 85 , , , , , , , , , ,
 27 16 54 88 82 18 45 64 45 87 , , , , , , , , , ,
   98 97 60 77 43 1 64 0 32 89 , , , , , , , , , ,
  77 90 68 83 9 76 10 10 95 12 , , , , , , , , , ,
   99 23 74 58 54 25 50 9 94 1 , , , , , , , , , ,

:noname >r cells [email protected] + @ swap cells r> + @ swap < ; is precedes
:noname >r cells [email protected] + swap cells r> + over @ over @ swap rot ! swap ! ; is exchange

: .array 100 0 do example i cells + ? loop cr ;

.array example 100 combsort .array


program Combsort_Demo
  implicit none

  integer, parameter :: num = 20
  real :: array(num)

  call random_seed
  call random_number(array)
  write(*,*) "Unsorted array:-"
  write(*,*) array
  write(*,*)
  call combsort(array)
  write(*,*) "Sorted array:-"
  write(*,*) array

contains

  subroutine combsort(a)

    real, intent(in out) :: a(:)
    real :: temp
    integer :: i, gap
    logical :: swapped = .true.

    gap = size(a)
    do while (gap > 1 .or. swapped)
      gap = gap / 1.3
      if (gap < 1) gap = 1
      swapped = .false.
      do i = 1, size(a)-gap
        if (a(i) > a(i+gap)) then
          temp = a(i)
          a(i) = a(i+gap)
          a(i+gap) = temp;
          swapped = .true.
        end if
      end do
    end do

  end subroutine combsort

end program Combsort_Demo


    itemCount = 20
    dim A(itemCount)
    dim tmp(itemCount)    'merge sort needs additionally same amount of storage

    for i = 1 to itemCount
        A(i) = int(rnd(1) * 100)
    next i

    print "Before Sort"
    call printArray itemCount

    call mergeSort 1,itemCount

    print "After Sort"
    call printArray itemCount
end

'------------------------------------------
sub mergeSort start, theEnd
    if theEnd-start < 1 then exit sub
    if theEnd-start = 1 then
        if A(start)>A(theEnd) then
            tmp=A(start)
            A(start)=A(theEnd)
            A(theEnd)=tmp
        end if
        exit sub
    end if
    middle = int((start+theEnd)/2)
    call mergeSort start, middle
    call mergeSort middle+1, theEnd
    call merge start, middle, theEnd
end sub

sub merge start, middle, theEnd
    i = start: j = middle+1: k = start
    while i<=middle OR j<=theEnd
        select case
        case i<=middle AND j<=theEnd
            if A(i)<=A(j) then
                tmp(k)=A(i)
                i=i+1
            else
                tmp(k)=A(j)
                j=j+1
            end if
            k=k+1
        case i<=middle
            tmp(k)=A(i)
            i=i+1
            k=k+1
        case else    'j<=theEnd
            tmp(k)=A(j)
            j=j+1
            k=k+1
        end select
    wend

    for i = start to theEnd
        A(i)=tmp(i)
    next
end sub

'===========================================
sub printArray itemCount
    for i = 1 to itemCount
        print using("###", A(i));
    next i
    print
end sub


package main

import (
    "fmt"
    "runtime"
    "strings"
)

var a = []int{170, 45, 75, -90, -802, 24, 2, 66}
var aMin, aMax = -1000, 1000

func main() {
    fmt.Println("before:", a)
    countingSort(a, aMin, aMax)
    fmt.Println("after: ", a)
}

func countingSort(a []int, aMin, aMax int) {
    defer func() {
        if x := recover(); x != nil {
            // one error we'll handle and print a little nicer message
            if _, ok := x.(runtime.Error); ok &&
                strings.HasSuffix(x.(error).Error(), "index out of range") {
                fmt.Printf("data value out of range (%d..%d)\n", aMin, aMax)
                return
            }
            // anything else, we re-panic
            panic(x)
        }
    }()

    count := make([]int, aMax-aMin+1)
    for _, x := range a {
        count[x-aMin]++
    }
    z := 0
    // optimization over task pseudocode:   variable c is used instead of
    // count[i-min].  This saves some unneccessary calculations.
    for i, c := range count {
        for ; c > 0; c-- {
            a[z] = i + aMin
            z++
        }
    }
}


def countingSort = { array ->
    def max = array.max()
    def min = array.min()
    // this list size allows use of Groovy's natural negative indexing
    def count = [0] * (max + 1 + [0, -min].max())
    array.each { count[it] ++ }
    (min..max).findAll{ count[it] }.collect{ [it]*count[it] }.flatten()
}


DEF || this rather nice solution is due to Silvio Meira
sort () = ()
sort (a : x) = sort {b <- x; b <= a } ++ a : sort { b <- x; b>a}
?


' version 21-10-2016
' compile with: fbc -s console
' for boundary checks on array's compile with: fbc -s console -exx

Sub compsort(bs() As Long)
    ' sort from lower bound to the highter bound
    ' array's can have subscript range from -2147483648 to +2147483647
    Dim As Long lb = LBound(bs)
    Dim As Long ub = UBound(bs)
    Dim As Long gap = ub - lb
    Dim As Long done, i

    Do
        gap = Int (gap / 1.3)
        If gap < 1 Then gap = 1
        done = 0
        For i = lb To ub - gap
            If bs(i) > bs(i + gap) Then
                Swap bs(i), bs(i + gap)
                done = 1
            End If
        Next
    Loop Until ((gap = 1) And (done = 0))

End Sub

Sub comp11sort(bs() As Long)
    ' sort from lower bound to the higher bound
    ' array's can have subscript range from -2147483648 to +2147483647
    Dim As Long lb = LBound(bs)
    Dim As Long ub = UBound(bs)
    Dim As Long gap = ub - lb
    Dim As Long done, i

    Do
        gap = Int(gap / 1.24733)
        If gap = 9 Or gap = 10 Then
            gap = 11
        ElseIf gap < 1 Then
            gap = 1
        End If
        done = 0
        For i = lb To ub - gap
            If bs(i) > bs(i + gap) Then
                Swap bs(i), bs(i + gap)
                done = 1
            End If
        Next
    Loop Until ((gap = 1) And (done = 0))

End Sub

' ------=< MAIN >=------

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
For i = a To b ' little shuffle
    Swap array(i), array(Int(Rnd * (b - a +1)) + a)
Next

Print "normal comb sort"
Print "unsorted ";
For i = a To b : Print Using "####"; array(i); : Next : Print
compsort(array())  ' sort the array
Print "  sorted ";
For i = a To b : Print Using "####"; array(i); : Next : Print

Print
Print "comb11 sort"
For i = a To b ' little shuffle
    Swap array(i), array(Int(Rnd * (b - a +1)) + a)
Next
Print "unsorted ";
For i = a To b : Print Using "####"; array(i); : Next : Print
comp11sort(array())  ' sort the array
Print "  sorted ";
For i = a To b : Print Using "####"; array(i); : Next : Print

' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End


to split :size :front :list
  if :size < 1 [output list :front :list]
  output split :size-1 (lput first :list :front) (butfirst :list)
end

to merge :small :large
  if empty? :small [output :large]
  ifelse lessequal? first :small first :large ~
    [output fput first :small merge butfirst :small :large] ~
    [output fput first :large merge butfirst :large :small]
end

to mergesort :list
  localmake "half split (count :list) / 2 [] :list
  if empty? first :half [output :list]
  output merge mergesort first :half mergesort last :half
end


msort([], []) :- !.
msort([X], [X]) :- !.
msort([X, Y| Xs], Ys) :-
    split([X, Y| Xs], X1s, X2s),
    msort(X1s, Y1s),
    msort(X2s, Y2s),
    merge(Y1s, Y2s, Ys).

split([], [], []).
split([X| Xs], [X| Ys], Zs) :-
    split(Xs, Zs, Ys).

merge([X| Xs], [Y| Ys], [X| Zs]) :-
    X @=< Y, !,
    merge(Xs, [Y| Ys], Zs).
merge([X| Xs], [Y| Ys], [Y| Zs]) :-
    X @> Y, !,
    merge([X | Xs], Ys, Zs).
merge([], Xs, Xs) :- !.
merge(Xs, [], Xs).


import Data.Array

countingSort :: (Ix n) => [n] -> n -> n -> [n]
countingSort l lo hi = concatMap (uncurry $ flip replicate) count
  where count = assocs . accumArray (+) 0 (lo, hi) . map (\i -> (i, 1)) $ l


class CountingSort {
  public static function sort(arr:Array<Int>) {
    var min = arr[0], max = arr[0];
    for (i in 1...arr.length) {
      if (arr[i] < min)
        min = arr[i];
      else if (arr[i] > max)
        max = arr[i];
    }

    var range = max - min + 1;
    var count = new Array<Int>();
    count.resize(range * arr.length);

    for (i in 0...range) count[i] = 0;
    for (i in 0...arr.length) count[arr[i] - min]++;

    var z = 0;
    for (i in min...(max + 1)) {
      for (j in 0...count[i - min])
        arr[z++] = i;
    }
  }
}

class Main {
  static function main() {
    var integerArray = [1, 10, 2, 5, -1, 5, -19, 4, 23, 0];
    Sys.println('Unsorted Integers: ' + integerArray);
    CountingSort.sort(integerArray);
    Sys.println('Sorted Integers:   ' + integerArray);
  }
}


procedure main()                                         #: demonstrate various ways to sort a list and string
   write("Sorting Demo using ",image(countingsort))
   writes("  on list : ")
   writex(UL)
   displaysort(countingsort,copy(UL))
end

procedure countingsort(X)                                #: return sorted list (integers only)
local T,lower,upper

   T := table(0)                                         # hash table as sparse array
   lower := upper := X[1]

   every x := !X do {
      if not ( integer(x) = x ) then runerr(x,101)       # must be integer
      lower >:= x                                        # minimum
      upper <:= x                                        # maximum
      T[x] +:= 1                                         # record x's and duplicates
      }

   every put(X := [],( 1 to T[i := lower to upper], i) ) # reconstitute with correct order and count
   return X
end


class SORT{T < $IS_LT{T}} is

  private afilter(a:ARRAY{T}, cmp:ROUT{T,T}:BOOL, p:T):ARRAY{T} is
    filtered ::= #ARRAY{T};
    loop v ::= a.elt!;
      if cmp.call(v, p) then
        filtered := filtered.append(|v|);
      end;
    end;
    return filtered;
  end;

  private mlt(a, b:T):BOOL is return a < b; end;
  private mgt(a, b:T):BOOL is return a > b; end;
  quick_sort(inout a:ARRAY{T}) is
    if a.size < 2 then return; end;
    pivot ::= a.median;
    left:ARRAY{T} := afilter(a, bind(mlt(_,_)), pivot);
    right:ARRAY{T} := afilter(a, bind(mgt(_,_)), pivot);
    quick_sort(inout left);
    quick_sort(inout right);
    res ::= #ARRAY{T};
    res := res.append(left, |pivot|,  right);
    a := res;
  end;
end;


Public Sub Main()
Dim siToSort As Short[] = [249, 28, 111, 36, 171, 98, 29, 448, 44, 147, 154, 46, 102, 183, 24,
                          120, 19, 123, 2, 17, 226, 11, 211, 25, 191, 205, 77]
Dim siStart As Short
Dim siGap As Short = siToSort.Max
Dim bSorting, bGap1 As Boolean

Print "To sort: -"
ShowWorking(siToSort)
Print

Repeat
  bSorting = False
  siStart = 0
  If siGap = 1 Then bGap1 = True

  Repeat
    If siToSort[siStart] > siToSort[siStart + siGap] Then
      Swap siToSort[siStart], siToSort[siStart + siGap]
      bSorting = True
    End If
    Inc siStart
  Until siStart + siGap > siToSort.Max

  If bSorting Then ShowWorking(siToSort)
  siGap /= 1.3
  If siGap < 1 Then siGap = 1

Until bSorting = False And bGap1 = True

End
'-----------------------------------------
Public Sub ShowWorking(siToSort As Short[])
Dim siCount As Short

For siCount = 0 To siToSort.Max
  Print Str(siToSort[siCount]);
  If siCount <> siToSort.Max Then Print ",";
Next

Print

End


local function merge(left_container, left_container_begin, left_container_end, right_container, right_container_begin, right_container_end, result_container, result_container_begin, comparator)
	while left_container_begin <= left_container_end do
		if right_container_begin > right_container_end then
			for i = left_container_begin, left_container_end do
				result_container[result_container_begin] = left_container[i]
				result_container_begin = result_container_begin + 1
			end

			return
		end

		if comparator(right_container[right_container_begin], left_container[left_container_begin]) then
			result_container[result_container_begin] = right_container[right_container_begin]
			right_container_begin = right_container_begin + 1
		else
			result_container[result_container_begin] = left_container[left_container_begin]
			left_container_begin = left_container_begin + 1
		end

		result_container_begin = result_container_begin + 1
	end

	for i = right_container_begin, right_container_end do
		result_container[result_container_begin] = right_container[i]
		result_container_begin = result_container_begin + 1
	end
end

local function mergesort_impl(container, container_begin, container_end, comparator)
	local range_length = (container_end - container_begin) + 1
	if range_length < 2 then return end
	local copy = {}
	local copy_len = 0

	for it = container_begin, container_end do
		copy_len = copy_len + 1
		copy[copy_len] = container[it]
	end

	local middle = bit.rshift(range_length, 1) -- or math.floor(range_length / 2)
	mergesort_impl(copy, 1, middle, comparator)
	mergesort_impl(copy, middle + 1, copy_len, comparator)
	merge(copy, 1, middle, copy, middle + 1, copy_len, container, container_begin, comparator)
end

local function mergesort_default_comparator(a, b)
	return a < b
end

function table.mergesort(container, comparator)
	if not comparator then
		comparator = mergesort_default_comparator
	end

	mergesort_impl(container, 1, #container, comparator)
end


List do(
    countingSort := method(min, max,
        count := list() setSize(max - min + 1) mapInPlace(0)
        foreach(x,
            count atPut(x - min, count at(x - min) + 1)
        )

        j := 0
        for(i, min, max,
            while(count at(i - min) > 0,
                atPut(j, i)
                count atPut(i - min, at(i - min) - 1)
                j = j + 1
            )
        )
    self)

    countingSortInPlace := method(
        countingSort(min, max)
    )
)

l := list(2, 3, -4, 5, 1)
l countingSortInPlace println # ==> list(-4, 1, 2, 3, 5)


100 PROGRAM "CountSrt.bas"
110 RANDOMIZE
120 NUMERIC ARRAY(5 TO 24)
130 CALL INIT(ARRAY)
140 CALL WRITE(ARRAY)
150 CALL COUNTINGSORT(ARRAY)
160 CALL WRITE(ARRAY)
170 DEF INIT(REF A)
180   FOR I=LBOUND(A) TO UBOUND(A)
190     LET A(I)=RND(98)+1
200   NEXT
210 END DEF
220 DEF WRITE(REF A)
230   FOR I=LBOUND(A) TO UBOUND(A)
240     PRINT A(I);
250   NEXT
260   PRINT
270 END DEF
280 DEF FMIN(REF A)
290   LET T=INF
300   FOR I=LBOUND(A) TO UBOUND(A)
310     LET T=MIN(A(I),T)
320   NEXT
330   LET FMIN=T
340 END DEF
350 DEF FMAX(REF A)
360   LET T=-INF
370   FOR I=LBOUND(A) TO UBOUND(A)
380     LET T=MAX(A(I),T)
390   NEXT
400   LET FMAX=T
410 END DEF
420 DEF COUNTINGSORT(REF A)
430   LET MX=FMAX(A):LET MN=FMIN(A):LET Z=LBOUND(A)
440   NUMERIC COUNT(0 TO MX-MN)
450   FOR I=0 TO UBOUND(COUNT)
460     LET COUNT(I)=0
470   NEXT
480   FOR I=Z TO UBOUND(A)
490     LET COUNT(A(I)-MN)=COUNT(A(I)-MN)+1
500   NEXT
510   FOR I=MN TO MX
520     DO WHILE COUNT(I-MN)>0
530       LET A(Z)=I:LET Z=Z+1:LET COUNT(I-MN)=COUNT(I-MN)-1
540     LOOP
550   NEXT
560 END DEF


csort =: monad define
  min =. <./y
  cnt =. 0 $~ 1+(>./y)-min
  for_a. y do.
    cnt =. cnt >:@{`[`]}~ a-min
  end.
  cnt # min+i.#cnt
)


public static void countingSort(int[] array, int min, int max){
	int[] count= new int[max - min + 1];
	for(int number : array){
		count[number - min]++;
	}
	int z= 0;
	for(int i= min;i <= max;i++){
		while(count[i - min] > 0){
			array[z]= i;
			z++;
			count[i - min]--;
		}
	}
}


  def sort(xs: List[Int]): List[Int] = xs match {
    case Nil => Nil
    case head :: tail =>
      val (less, notLess) = tail.partition(_ < head) // Arbitrarily partition list in two
      sort(less) ++ (head :: sort(notLess))          // Sort each half
  }


package main

import "fmt"

func main() {
    a := []int{170, 45, 75, -90, -802, 24, 2, 66}
    fmt.Println("before:", a)
    combSort(a)
    fmt.Println("after: ", a)
}

func combSort(a []int) {
    if len(a) < 2 {
        return
    }
    for gap := len(a); ; {
        if gap > 1 {
            gap = gap * 4 / 5
        }
        swapped := false
        for i := 0; ; {
            if a[i] > a[i+gap] {
                a[i], a[i+gap] = a[i+gap], a[i]
                swapped = true
            }
            i++
            if i+gap >= len(a) {
                break
            }
        }
        if gap == 1 && !swapped {
            break
        }
    }
}


def makeSwap = { a, i, j -> print "."; a[i] ^= a[j]; a[j] ^= a[i]; a[i] ^= a[j] }

def checkSwap = { a, i, j -> [(a[i] > a[j])].find { it }.each { makeSwap(a, i, j) } }

def combSort = { input ->
    def swap = checkSwap.curry(input)
    def size = input.size()
    def gap = size
    def swapped = true
    while (gap != 1 || swapped) {
        gap = (gap / 1.247330950103979) as int
        gap = (gap < 1) ? 1 : gap
        swapped = (0..<(size-gap)).any { swap(it, it + gap) }
    }
    input
}


msort(a) = if iseod(first next a) then a else merge(msort(b0),msort(b1)) fi
  where
   p = false fby not p;
   b0 = a whenever p;
   b1 = a whenever not p;
   just(a) = ja
      where
         ja = a fby if iseod ja then eod else next a fi;
      end;
   merge(x,y) = if takexx then xx else yy fi
     where
      xx = (x) upon takexx;
      yy = (y) upon not takexx;
      takexx = if iseod(yy) then true elseif
                  iseod(xx) then false else xx <= yy fi;
     end;
  end;


module checkit {
	\\ merge sort
	group merge {
		function sort(right as stack) {
			if len(right)<=1 then =right : exit
			left=.sort(stack up right, len(right) div 2 )
			right=.sort(right)
			\\ stackitem(right) is same as stackitem(right,1)
			if stackitem(left, len(left))<=stackitem(right) then
				\\ !left take items from left for merging
				\\ so after this left and right became empty stacks
				=stack:=!left, !right
				exit
			end if
			=.merge(left, right)
		}
		function sortdown(right as stack) {
			if len(right)<=1 then =right : exit
			left=.sortdown(stack up right, len(right) div 2 )
			right=.sortdown(right)
			if stackitem(left, len(left))>stackitem(right) then
				=stack:=!left, !right : exit
			end if
			=.mergedown(left, right)
		}
		\\ left and right are pointers to stack objects
		\\ here we pass by value the pointer not the data
		function merge(left as stack, right as stack) {
			result=stack
			while len(left) > 0 and len(right) > 0
				if stackitem(left,1) <= stackitem(right) then
					result=stack:=!result, !(stack up left, 1)
				else
					result=stack:=!result, !(stack up right, 1)
				end if
			end while
			if len(right) > 0 then  result=stack:= !result,!right
			if len(left) > 0 then result=stack:= !result,!left
			=result
		}
		function mergedown(left as stack, right as stack) {
			result=stack
			while len(left) > 0 and len(right) > 0
				if stackitem(left,1) > stackitem(right) then
					result=stack:=!result, !(stack up left, 1)
				else
					result=stack:=!result, !(stack up right, 1)
				end if
			end while
			if len(right) > 0 then  result=stack:= !result,!right
			if len(left) > 0 then result=stack:= !result,!left
			=result
		}
	}
	k=stack:=7, 5, 2, 6, 1, 4, 2, 6, 3
	print merge.sort(k)
	print len(k)=0   ' we have to use merge.sort(stack(k)) to pass a copy of k

	\\ input array  (arr is a pointer to array)
	arr=(10,8,9,7,5,6,2,3,0,1)
	\\ stack(array pointer) return a stack with a copy of array items
	\\ array(stack pointer) return an array, empty the stack

	arr2=array(merge.sort(stack(arr)))
	Print type$(arr2)
	Dim a()
	\\ a() is an array as a value, so we just copy arr2 to a()
	a()=arr2
	\\ to prove we add 1 to each element of arr2
	arr2++
	Print a()  ' 0,1,2,3,4,5,6,7,8,9
	Print arr2  ' 1,2,3,4,5,6,7,8,9,11
	p=a()  ' we get a pointer
	\\ a() has a double pointer inside
	\\ so a() get just the inner pointer
	a()=array(merge.sortdown(stack(p)))
	\\ so now p (which use the outer pointer)
	\\ still points to a()
	print p   ' p point to a()

}
checkit


var countSort = function(arr, min, max) {
    var i, z = 0, count = [];

    for (i = min; i <= max; i++) {
        count[i] = 0;
    }

    for (i=0; i < arr.length; i++) {
        count[arr[i]]++;
    }

    for (i = min; i <= max; i++) {
        while (count[i]-- > 0) {
            arr[z++] = i;
        }
    }

}


def countingSort(min; max):
  . as $in
  | reduce range(0;length) as $i
      ( {};
        ($in[$i]|tostring) as $s | .[$s] += 1 # courtesy of the fact that in jq, (null+1) is 1
      )
  | . as $hash
  # now construct the answer:
  | reduce range(min; max+1) as $i
      ( [];
        ($i|tostring) as $s
        | if $hash[$s] == null then .
          else reduce range(0; $hash[$s]) as $j (.; . + [$i])
          end
      );


function countsort(a::Vector{<:Integer})
    lo, hi = extrema(a)
    b   = zeros(a)
    cnt = zeros(eltype(a), hi - lo + 1)
    for i in a cnt[i-lo+1] += 1 end
    z = 1
    for i in lo:hi
        while cnt[i-lo+1] > 0
            b[z] = i
            z += 1
            cnt[i-lo+1] -= 1
        end
    end
    return b
end

v = rand(UInt8, 20)
println("# unsorted bytes: $v\n -> sorted bytes: $(countsort(v))")
v = rand(1:2 ^ 10, 20)
println("# unsorted integers: $v\n -> sorted integers: $(countsort(v))")


(define (split-by l p k)
  (let loop ((low '())
             (high '())
             (l l))
    (cond ((null? l)
           (k low high))
          ((p (car l))
           (loop low (cons (car l) high) (cdr l)))
          (else
           (loop (cons (car l) low) high (cdr l))))))

(define (quicksort l gt?)
  (if (null? l)
      '()
      (split-by (cdr l)
                (lambda (x) (gt? x (car l)))
                (lambda (low high)
                  (append (quicksort low gt?)
                          (list (car l))
                          (quicksort high gt?))))))

(quicksort '(1 3 5 7 9 8 6 4 2) >)


import Data.List
import Control.Arrow
import Control.Monad

flgInsert x xs = ((x:xs==) &&& id)$ insert x xs

gapSwapping k = (and *** concat. transpose). unzip
  . map (foldr (\x (b,xs) -> first (b &&)$ flgInsert x xs) (True,[]))
  . transpose. takeWhile (not.null). unfoldr (Just. splitAt k)

combSort xs = (snd. fst) $ until (\((b,_),g)-> b && g==1)
    (\((_,xs),g) ->(gapSwapping g xs, fg g)) ((False,xs), fg $ length xs)
  where fg = max 1. truncate. (/1.25). fromIntegral


class CombSort {
  @:generic
  public static function sort<T>(arr:Array<T>) {
    var gap:Float = arr.length;
    var swaps = true;
    while (gap > 1 || swaps) {
      gap /= 1.247330950103979;
      if (gap < 1) gap = 1.0;
      var i = 0;
      swaps = false;
      while (i + gap < arr.length) {
        var igap = i + Std.int(gap);
        if (Reflect.compare(arr[i], arr[igap]) > 0) {
          var temp = arr[i];
          arr[i] = arr[igap];
          arr[igap] = temp;
          swaps = true;
        }
        i++;
      }
    }
  }
}

class Main {
  static function main() {
    var integerArray   = [1, 10, 2, 5, -1, 5, -19, 4, 23, 0];
    var floatArray = [1.0, -3.2, 5.2, 10.8, -5.7, 7.3,
                      3.5, 0.0, -4.1, -9.5];
    var stringArray = ['We', 'hold', 'these', 'truths', 'to',
                       'be', 'self-evident', 'that', 'all',
                       'men', 'are', 'created', 'equal'];
    Sys.println('Unsorted Integers: ' + integerArray);
    CombSort.sort(integerArray);
    Sys.println('Sorted Integers:   ' + integerArray);
    Sys.println('Unsorted Floats:   ' + floatArray);
    CombSort.sort(floatArray);
    Sys.println('Sorted Floats:     ' + floatArray);
    Sys.println('Unsorted Strings:  ' + stringArray);
    CombSort.sort(stringArray);
    Sys.println('Sorted Strings:    ' + stringArray);
  }
}


procedure main()                     #: demonstrate various ways to sort a list and string
   demosort(combsort,[3, 14, 1, 5, 9, 2, 6, 3],"qwerty")
end

procedure combsort(X,op)                  #: return sorted X
local gap,swapped,i

   op := sortop(op,X)                     # select how and what we sort

   swappped := gap := *X                  # initialize gap size and say swapped
   until /swapped & gap = 1 do {
      gap := integer(gap / 1.25)          # update the gap value for a next comb
      gap <:= 1                           # minimum gap of 1
      swapped := &null

       i := 0
       until (i +:= 1) + gap > *X do      # a single "comb" over the input list
         if op(X[i+gap],X[i]) then
            X[i+1] :=: X[swapped := i]    # swap and flag as unsorted
      }
   return X
end


merge := proc(arr, left, mid, right)
	local i, j, k, n1, n2, L, R;
	n1 := mid-left+1:
	n2 := right-mid:
	L := Array(1..n1):
	R := Array(1..n2):
	for i from 0 to n1-1 do
		L(i+1) :=arr(left+i):
	end do:
	for j from 0 to n2-1 do
		R(j+1) := arr(mid+j+1):
	end do:
	i := 1:
	j := 1:
	k := left:
	while(i <= n1 and j <= n2) do
		if (L[i] <= R[j]) then
			arr[k] := L[i]:
			i++:
		else
			arr[k] := R[j]:
			j++:
		end if:
		k++:
	end do:
	while(i <= n1) do
		arr[k] := L[i]:
		i++:
		k++:
	end do:
	while(j <= n2) do
		arr[k] := R[j]:
		j++:
		k++:
	end do:
end proc:
arr := Array([17,3,72,0,36,2,3,8,40,0]);
mergeSort(arr,1,numelems(arr)):
arr;


MergeSort[m_List] := Module[{middle},
  If[Length[m] >= 2,
   middle = Ceiling[Length[m]/2];
   Apply[Merge,
    Map[MergeSort, Partition[m, middle, middle, {1, 1}, {}]]],
   m
   ]
  ]

Merge[left_List, right_List] := Module[
  {leftIndex = 1, rightIndex = 1},
  Table[
   Which[
    leftIndex > Length[left], right[[rightIndex++]],
    rightIndex > Length[right], left[[leftIndex++]],
    left[[leftIndex]] <= right[[rightIndex]], left[[leftIndex++]],
    True, right[[rightIndex++]]],
   {Length[left] + Length[right]}]
  ]


// version 1.1.0

fun countingSort(array: IntArray) {
    if (array.isEmpty()) return
    val min = array.min()!!
    val max = array.max()!!
    val count = IntArray(max - min + 1)  // all elements zero by default
    for (number in array) count[number - min]++
    var z = 0
    for (i in min..max)
        while (count[i - min] > 0) {
            array[z++] = i
            count[i - min]--
        }
}

fun main(args: Array<String>) {
    val array = intArrayOf(4, 65, 2, -31, 0, 99, 2, 83, 782, 1)
    println("Original : ${array.asList()}")
    countingSort(array)
    println("Sorted   : ${array.asList()}")
}


val .countingSort = f(.array) {
    val .min, .max = minmax(.array)
    var .count = arr .max-.min+1, 0
    for .i in .array { .count[.i-.min+1] += 1 }
    for .i of .count { _for ~= arr .count[.i], .i+.min-1 }
}

val .data = [7, 234, -234, 9, 43, 123, 14]

writeln "Original: ", .data
writeln "Sorted  : ", .countingSort(.data)


function CountingSort( f )
    local min, max = math.min( unpack(f) ), math.max( unpack(f) )
    local count = {}
    for i = min, max do
        count[i] = 0
    end

    for i = 1, #f do
        count[ f[i] ] = count[ f[i] ] + 1
    end

    local z = 1
    for i = min, max do
        while count[i] > 0 do
            f[z] = i
            z = z + 1
            count[i] = count[i] - 1
        end
    end

end

f = { 15, -3, 0, -1, 5, 4, 5, 20, -8 }

CountingSort( f )

for i in next, f do
    print( f[i] )
end


const proc: quickSort (inout array elemType: arr, in integer: left, in integer: right) is func
  local
    var elemType: compare_elem is elemType.value;
    var integer: less_idx is 0;
    var integer: greater_idx is 0;
    var elemType: help is elemType.value;
  begin
    if right > left then
      compare_elem := arr[right];
      less_idx := pred(left);
      greater_idx := right;
      repeat
        repeat
          incr(less_idx);
        until arr[less_idx] >= compare_elem;
        repeat
          decr(greater_idx);
        until arr[greater_idx] <= compare_elem or greater_idx = left;
        if less_idx < greater_idx then
          help := arr[less_idx];
          arr[less_idx] := arr[greater_idx];
          arr[greater_idx] := help;
        end if;
      until less_idx >= greater_idx;
      arr[right] := arr[less_idx];
      arr[less_idx] := compare_elem;
      quickSort(arr, left, pred(less_idx));
      quickSort(arr, succ(less_idx), right);
    end if;
  end func;

const proc: quickSort (inout array elemType: arr) is func
  begin
    quickSort(arr, 1, length(arr));
  end func;


100 PROGRAM "CombSrt.bas"
110 RANDOMIZE
120 NUMERIC ARRAY(11 TO 30)
130 CALL INIT(ARRAY)
140 CALL WRITE(ARRAY)
150 CALL COMBSORT(ARRAY)
160 CALL WRITE(ARRAY)
170 DEF INIT(REF A)
180   FOR I=LBOUND(A) TO UBOUND(A)
190     LET A(I)=RND(98)+1
200   NEXT
210 END DEF
220 DEF WRITE(REF A)
230   FOR I=LBOUND(A) TO UBOUND(A)
240     PRINT A(I);
250   NEXT
260   PRINT
270 END DEF
280 DEF COMBSORT(REF A)
290   LET N,GAP=UBOUND(A):LET SW=1
300   DO WHILE GAP>1 OR SW
310     LET GAP=MAX(INT(GAP/1.3),1):LET SW=0
320     FOR I=LBOUND(A) TO N-GAP
330       IF A(I)>A(I+GAP) THEN
340         LET T=A(I):LET A(I)=A(I+GAP):LET A(I+GAP)=T
350         LET SW=1
360       END IF
370     NEXT
380   LOOP
390 END DEF


combSort=:3 :0
  gap=. #y
  whilst.1 < gap+swaps do.
    swaps=. 0
    i=. i.2,gap=. 1 >. <.gap%1.25
    while.{:$i=.i #"1~ ({: i) < #y do.
      swaps=.swaps+#{:k=.i #"1~b=. >/ i{y
      i=. i+gap
      y=.((|.k){y) k} y
    end.
  end.
  y
)


function list = mergeSort(list)

    if numel(list) <= 1
        return
    else
        middle = ceil(numel(list) / 2);
        left = list(1:middle);
        right = list(middle+1:end);

        left = mergeSort(left);
        right = mergeSort(right);

        if left(end) <= right(1)
            list = [left right];
            return
        end

        %merge(left,right)
        counter = 1;
        while (numel(left) > 0) && (numel(right) > 0)
            if(left(1) <= right(1))
                list(counter) = left(1);
                left(1) = [];
            else
                list(counter) = right(1);
                right(1) = [];
            end
            counter = counter + 1;
        end

        if numel(left) > 0
            list(counter:end) = left;
        elseif numel(right) > 0
            list(counter:end) = right;
        end
        %end merge
    end %if
end %mergeSort


divert(-1)

define(`randSeed',141592653)
define(`setRand',
   `define(`randSeed',ifelse(eval($1<10000),1,`eval(20000-$1)',`$1'))')
define(`rand_t',`eval(randSeed^(randSeed>>13))')
define(`random',
   `define(`randSeed',eval((rand_t^(rand_t<<18))&0x7fffffff))randSeed')

define(`set',`define(`$1[$2]',`$3')')
define(`get',`defn(`$1[$2]')')
define(`new',`set($1,size,0)')
define(`append',
   `set($1,size,incr(get($1,size)))`'set($1,get($1,size),$2)')
define(`deck',
   `new($1)for(`x',1,$2,
         `append(`$1',eval(random%$3))')')
define(`for',
   `ifelse($#,0,``$0'',
   `ifelse(eval($2<=$3),1,
   `pushdef(`$1',$2)$4`'popdef(`$1')$0(`$1',incr($2),$3,`$4')')')')
define(`show',
   `for(`x',1,get($1,size),`get($1,x) ')')

define(`countingsort',
   `for(`x',$2,$3,`set(count,x,0)')`'for(`x',1,get($1,size),
      `set(count,get($1,x),incr(get(count,get($1,x))))')`'define(`z',
      1)`'for(`x',$2,$3,
         `for(`y',1,get(count,x),
            `set($1,z,x)`'define(`z',incr(z))')')')

divert
deck(`a',10,100)
show(`a')
countingsort(`a',0,99)
show(`a')


countingSort[list_] := Module[{minElem, maxElem, count, z, number},
  minElem = Min[list]; maxElem = Max[list];
  count = ConstantArray[0, (maxElem - minElem + 1)];
  For[number = 1, number < Length[list], number++,
   count[[number - minElem + 1]] = count[[number - minElem + 1]] + 1;] ;
  z = 1;
  For[i = minElem, i < maxElem, i++,
   While[count[[i - minElem + 1]] > 0,
    list[[z]] = i; z++;
    count[[i - minElem + 1]] = count[[i - minElem + 1]] - 1;]
   ];
  ]


function list = countingSort(list)

    minElem = min(list);
    maxElem = max(list);

    count = zeros((maxElem-minElem+1),1);

    for number = list
        count(number - minElem + 1) = count(number - minElem + 1) + 1;
    end

    z = 1;

    for i = (minElem:maxElem)
        while( count(i-minElem +1) > 0)
            list(z) = i;
            z = z+1;
            count(i - minElem + 1) = count(i - minElem + 1) - 1;
        end
    end

end %countingSort


a := [2,5,8,7,0,9,1,3,6,4];
qsort(a);
print(a);

proc qsort(rw a);
  if #a > 1 then
    pivot := a(#a div 2 + 1);
    l := 1;
    r := #a;
    (while l < r)
      (while a(l) < pivot) l +:= 1; end;
      (while a(r) > pivot) r -:= 1; end;
      swap(a(l), a(r));
    end;
    qsort(a(1..l-1));
    qsort(a(r+1..#a));
  end if;
end proc;

proc swap(rw x, rw y);
  [y,x] := [x,y];
end proc;


public static <E extends Comparable<? super E>> void sort(E[] input) {
    int gap = input.length;
    boolean swapped = true;
    while (gap > 1 || swapped) {
        if (gap > 1) {
            gap = (int) (gap / 1.3);
        }
        swapped = false;
        for (int i = 0; i + gap < input.length; i++) {
            if (input[i].compareTo(input[i + gap]) > 0) {
                E t = input[i];
                input[i] = input[i + gap];
                input[i + gap] = t;
                swapped = true;
            }
        }
    }
}


  // Node 5.4.1 tested implementation (ES6)
  function is_array_sorted(arr) {
      var sorted = true;
      for (var i = 0; i < arr.length - 1; i++) {
          if (arr[i] > arr[i + 1]) {
              sorted = false;
              break;
          }
      }
      return sorted;
  }

  // Array to sort
  var arr = [4, 9, 0, 3, 1, 5];

  var iteration_count = 0;
  var gap = arr.length - 2;
  var decrease_factor = 1.25;

  // Until array is not sorted, repeat iterations
  while (!is_array_sorted(arr)) {
      // If not first gap
      if (iteration_count > 0)
      // Calculate gap
          gap = (gap == 1) ? gap : Math.floor(gap / decrease_factor);

      // Set front and back elements and increment to a gap
      var front = 0;
      var back = gap;
      while (back <= arr.length - 1) {
          // If elements are not ordered swap them
          if (arr[front] > arr[back]) {
              var temp = arr[front];
              arr[front] = arr[back];
              arr[back] = temp;
          }

          // Increment and re-run swapping
          front += 1;
          back += 1;
      }
      iteration_count += 1;
  }

  // Print the sorted array
  console.log(arr);
}


merge(a, b) := block(
   [c: [ ], i: 1, j: 1, p: length(a), q: length(b)],
   while i <= p and j <= q do (
      if a[i] < b[j] then (
         c: endcons(a[i], c),
         i: i + 1
      ) else (
         c: endcons(b[j], c),
         j: j + 1
      )
   ),
   if i > p then append(c, rest(b, j - 1)) else append(c, rest(a, i - 1))
)$

mergesort(u) := block(
   [n: length(u), k, a, b],
   if n <= 1 then u else (
      a: rest(u, k: quotient(n, 2)),
      b: rest(u, k - n),
      merge(mergesort(a), mergesort(b))
   )
)$


fn mergesort arr =
(
	local left = #()
	local right = #()
	local result = #()
	if arr.count < 2 then return arr
	else
	(
		local mid = arr.count/2
		for i = 1 to mid do
		(
			append left arr[i]
		)
		for i = (mid+1) to arr.count do
		(
			append right arr[i]
		)
		left = mergesort left
		right = mergesort right
		if left[left.count] <= right[1] do
		(
			join left right
			return left
		)
		result = _merge left right
		return result
	)
)

fn _merge a b =
(
	local result = #()
	while a.count > 0 and b.count > 0 do
	(
		if a[1] <= b[1] then
		(
			append result a[1]
			a = for i in 2 to a.count collect a[i]
		)
		else
		(
			append result b[1]
			b = for i in 2 to b.count collect b[i]
		)
	)
	if a.count > 0 do
	(
		join result a
	)
	if b.count > 0 do
	(
		join result b
	)
	return result
)


fn countingSort arr =
(
	if arr.count < 2 do return arr
	local minVal = amin arr
	local maxVal = amax arr
	local count = for i in 1 to (maxVal-minVal+1) collect 0
	for i in arr do
	(
		count[i-minVal+1] = count[i-minVal+1] + 1
	)
	local z = 1
	for i = minVal to maxVal do
	(
		while (count[i-minVal+1]>0) do
		(
			arr[z] = i
			z += 1
			count[i-minVal+1] = count[i-minVal+1] - 1
		)

	)
	return arr
)


MODULE Counting EXPORTS Main;

IMPORT IO, Fmt;

VAR test := ARRAY [1..8] OF INTEGER {80, 10, 40, 60, 50, 30, 20, 70};

PROCEDURE Sort(VAR a: ARRAY OF INTEGER; min, max: INTEGER) =
  VAR range := max - min + 1;
      count := NEW(REF ARRAY OF INTEGER, range);
      z := 0;
  BEGIN
    FOR i := FIRST(count^) TO LAST(count^) DO
      count[i] := 0;
    END;

    FOR i := FIRST(a) TO LAST(a) DO
      INC(count[a[i] - min]);
    END;

    FOR i := min TO max DO
      WHILE (count[i - min] > 0) DO
        a[z] := i;
        INC(z);
        DEC(count[i - min]);
      END;
    END;
  END Sort;

BEGIN
  IO.Put("Unsorted: ");
  FOR i := FIRST(test) TO LAST(test) DO
    IO.Put(Fmt.Int(test[i]) & " ");
  END;
  IO.Put("\n");
  Sort(test, 10, 80);
  IO.Put("Sorted: ");
  FOR i := FIRST(test) TO LAST(test) DO
    IO.Put(Fmt.Int(test[i]) & " ");
  END;
  IO.Put("\n");
END Counting.


func quicksort (a) {
    a.len < 2 && return(a);
    var p = a.pop_rand;          # to avoid the worst cases
    __FUNC__(a.grep{ .< p}) + [p] + __FUNC__(a.grep{ .>= p});
}


# Input should be the array to be sorted.
def combsort:

  # As soon as "condition" is true, emit . and stop:
  def do_until(condition; next):
    def u: if condition then . else (next|u) end;
  u;

  def swap(i;j):
    if i==j then . else .[i] as $tmp | .[i] = .[j] | .[j] = $tmp end;

   . as $in
  | length as $length
    # state: [gap, swaps, array] where:
    #   gap is the gap size;
    #   swaps is a boolean flag indicating a swap has occurred,
    #         implying that the array might not be sorted;
    #   array is the current state of the array being sorted
  | [ $length, false, $in ]
  | do_until( .[0] == 1 and .[1] == false;
      # update the gap value for the next "comb":
      ([1, ((.[0] / 1.25) | floor)] | max) as $gap   # minimum gap is 1

      # state: [i, swaps, array]
      | [0, false, .[2]]
      # a single "comb" over the input list:
      | do_until( (.[0] + $gap) >= $length;
          .[0] as $i
          | if .[2][$i] > .[2][$i+$gap] then
              [$i+1, true, (.[2]|swap($i; $i+$gap))]
            else .[0] += 1
            end)
      | .[0] = $gap )
  | .[2] ;


# v0.6

function combsort!(x::Array)::Array
    gap, swaps = length(x), true
    while gap > 1 || swaps
        gap = floor(Int, gap / 1.25)
        i, swaps = 0, false
        while i + gap < length(x)
            if x[i+1] > x[i+1+gap]
                x[i+1], x[i+1+gap] = x[i+1+gap], x[i+1]
                swaps = true
            end
            i += 1
        end
    end
    return x
end

x = randn(100)
@show x combsort!(x)
@assert issorted(x)


// version 1.1.2

fun <T : Comparable<T>> combSort(input: Array<T>) {
    var gap = input.size
    if (gap <= 1) return  // already sorted
    var swaps = false
    while (gap > 1 || swaps) {
        gap = (gap / 1.247331).toInt()
        if (gap < 1) gap = 1
        var i = 0
        swaps = false
        while (i + gap < input.size) {
            if (input[i] > input[i + gap]) {
                val tmp = input[i]
                input[i] = input[i + gap]
                input[i + gap] = tmp
                swaps = true
            }
            i++
        }
    }
}

fun main(args: Array<String>) {
    val ia = arrayOf(28, 44, 46, 24, 19, 2, 17, 11, 25, 4)
    println("Unsorted : ${ia.contentToString()}")
    combSort(ia)
    println("Sorted   : ${ia.contentToString()}")
    println()
    val ca = arrayOf('X', 'B', 'E', 'A', 'Z', 'M', 'S', 'L', 'Y', 'C')
    println("Unsorted : ${ca.contentToString()}")
    combSort(ca)
    println("Sorted   : ${ca.contentToString()}")
}


:- module merge_sort.

:- interface.

:- import_module list.

:- type split_error ---> split_error.

:- func merge_sort(list(T)) = list(T).
:- pred merge_sort(list(T)::in, list(T)::out) is det.

:- implementation.

:- import_module int, exception.

merge_sort(U) = S :- merge_sort(U, S).

merge_sort(U, S) :- merge_sort(list.length(U), U, S).

:- pred merge_sort(int::in, list(T)::in, list(T)::out) is det.
merge_sort(L, U, S) :-
    ( L > 1 ->
        H = L // 2,
        ( split(H, U, F, B) ->
            merge_sort(H, F, SF),
            merge_sort(L - H, B, SB),
            merge_sort.merge(SF, SB, S)
        ; throw(split_error) )
    ; S = U ).

:- pred split(int::in, list(T)::in, list(T)::out, list(T)::out) is semidet.
split(N, L, S, E) :-
    ( N = 0 -> S = [], E = L
    ; N > 0, L = [H | L1], S = [H | S1],
      split(N - 1, L1, S1, E) ).

:- pred merge(list(T)::in, list(T)::in, list(T)::out) is det.
merge([], [], []).
merge([X|Xs], [], [X|Xs]).
merge([], [Y|Ys], [Y|Ys]).
merge([X|Xs], [Y|Ys], M) :-
    ( compare(>, X, Y) ->
        merge_sort.merge([X|Xs], Ys, M0),
        M = [Y|M0]
    ; merge_sort.merge(Xs, [Y|Ys], M0),
        M = [X|M0] ).


DEFINITION MODULE MSIterat;

PROCEDURE IterativeMergeSort( VAR a : ARRAY OF INTEGER);

END MSIterat.


def countingSort(array, min, max)
        count = {0} * (max - min + 1)

        for number in array
                count[number - min] += 1
        end

        z = 0
        for i in range(min, max)
                while count[i - min] > 0
                        array[z] = i
                        z += 1
                        count[i - min] -= 1;
                end
        end
end


/* NetRexx */
options replace format comments java crossref savelog symbols binary

import java.util.List

icounts = [int -
      1,   3,   6,   2,   7,  13,  20,  12,  21,  11 -
  ,  22,  10,  23,   9,  24,   8,  25,  43,  62,  42 -
  ,  63,  41,  18,  42,  17,  43,  16,  44,  15,  45 -
  ,  14,  46,  79, 113,  78, 114,  77,  39,  78,  38 -
]
scounts = int[icounts.length]

System.arraycopy(icounts, 0, scounts, 0, icounts.length)
lists = [ -
     icounts -
  ,  countingSort(scounts) -
]

loop ln = 0 to lists.length - 1
  cl = lists[ln]
  rep = Rexx('')
  loop ct = 0 to cl.length - 1
    rep = rep cl[ct]
    end ct
    say '['rep.strip.changestr(' ', ',')']'
  end ln

return

method getMin(array = int[]) public constant binary returns int

  amin = Integer.MAX_VALUE
  loop x_ = 0 to array.length - 1
    if array[x_] < amin then
      amin = array[x_]
    end x_

  return amin

method getMax(array = int[]) public constant binary returns int

  amax = Integer.MIN_VALUE
  loop x_ = 0 to array.length - 1
    if array[x_] > amax then
      amax = array[x_]
    end x_

  return amax

method countingSort(array = int[], amin = getMin(array), amax = getMax(array)) public constant binary returns int[]

  count = int[amax - amin + 1]
  loop nr = 0 to array.length - 1
    numbr = array[nr]
    count[numbr - amin] = count[numbr - amin] + 1
    end nr

  z_ = 0

  loop i_ = amin to amax
    loop label count while count[i_ - amin] > 0
      array[z_] = i_
      z_ = z_ + 1
      count[i_ - amin] = count[i_ - amin] - 1
      end count
    end i_

  return array


PROCEDURE QUICKSORT(A); REAL ARRAY A;
BEGIN

    PROCEDURE QS(A, FIRST, LAST); REAL ARRAY A; INTEGER FIRST, LAST;
    BEGIN
        INTEGER LEFT, RIGHT;
        LEFT := FIRST; RIGHT := LAST;
        IF RIGHT - LEFT + 1 > 1 THEN
        BEGIN
            REAL PIVOT;
            PIVOT := A((LEFT + RIGHT) // 2);
            WHILE LEFT <= RIGHT DO
            BEGIN
                WHILE A(LEFT) < PIVOT DO LEFT := LEFT + 1;
                WHILE A(RIGHT) > PIVOT DO RIGHT := RIGHT - 1;
                IF LEFT <= RIGHT THEN
                BEGIN
                    REAL SWAP;
                    SWAP := A(LEFT); A(LEFT) := A(RIGHT); A(RIGHT) := SWAP;
                    LEFT := LEFT + 1; RIGHT := RIGHT - 1;
                END;
            END;
            QS(A, FIRST, RIGHT);
            QS(A, LEFT, LAST);
        END;
    END QS;

    QS(A, LOWERBOUND(A, 1), UPPERBOUND(A, 1));

END QUICKSORT;


'randomize 0.5
itemCount = 20
    dim item(itemCount)
    for i = 1 to itemCount
        item(i) = int(rnd(1) * 100)
    next i
    print "Before Sort"
    for i = 1 to itemCount
        print item(i)
    next i
    print: print
't0=time$("ms")

    gap=itemCount
    while gap>1 or swaps <> 0
        gap=int(gap/1.25)
        'if gap = 10 or gap = 9 then gap = 11    'uncomment to get Combsort11
        if gap <1 then gap = 1
        i = 1
        swaps = 0
        for i = 1 to itemCount-gap
            if item(i) > item(i + gap) then
                temp = item(i)
                item(i) = item(i + gap)
                item(i + gap) = temp
                swaps = 1
            end if
        next
    wend

    print "After Sort"
't1=time$("ms")
'print t1-t0

    for i = 1 to itemCount
        print item(i)
    next i
end


function combsort(t)
  local gapd, gap, swaps = 1.2473, #t, 0
  while gap + swaps > 1 do
    local k = 0
    swaps = 0
    if gap > 1 then gap = math.floor(gap / gapd) end
    for k = 1, #t - gap do
      if t[k] > t[k + gap] then
        t[k], t[k + gap], swaps = t[k + gap], t[k], swaps + 1
      end
    end
  end
  return t
end

print(unpack(combsort{3,5,1,2,7,4,8,3,6,4,1}))


using System;
using System.Console;
using Nemerle.Collections;

module Mergesort
{
    MergeSort[TEnu, TItem] (sort_me : TEnu) : list[TItem]
      where TEnu  : Seq[TItem]
      where TItem : IComparable
    {
        def split(xs) {
            def loop (zs, xs, ys) {
                |(x::y::zs, xs, ys) => loop(zs, x::xs, y::ys)
                |(x::[], xs, ys) => (x::xs, ys)
                |([], xs, ys) => (xs, ys)
            }

            loop(xs, [], [])
        }

        def merge(xs, ys) {
            def loop(res, xs, ys) {
                |(res, [], []) => res.Reverse()
                |(res, x::xs, []) => loop(x::res, xs, [])
                |(res, [], y::ys) => loop(y::res, [], ys)
                |(res, x::xs, y::ys) => if (x.CompareTo(y) < 0) loop(x::res, xs, y::ys)
                                        else loop(y::res, x::xs, ys)
            }
            loop ([], xs, ys)
        }

        def ms(xs) {
            |[] => []
            |[x] => [x]
            |_ => { def (left, right) = split(xs); merge(ms(left), ms(right)) }
        }

        ms(sort_me.NToList())
    }

    Main() : void
    {
        def test1 = MergeSort([1, 5, 9, 2, 7, 8, 4, 6, 3]);
        def test2 = MergeSort(array['a', 't', 'w', 'f', 'c', 'y', 'l']);
        WriteLine(test1);
        WriteLine(test2);
    }
}


/* NetRexx */
options replace format comments java crossref savelog symbols binary

import java.util.List

placesList = [String -
    "UK  London",     "US  New York",   "US  Boston",     "US  Washington" -
  , "UK  Washington", "US  Birmingham", "UK  Birmingham", "UK  Boston"     -
]

lists = [ -
    placesList -
  , mergeSort(String[] Arrays.copyOf(placesList, placesList.length)) -
]

loop ln = 0 to lists.length - 1
  cl = lists[ln]
  loop ct = 0 to cl.length - 1
    say cl[ct]
    end ct
    say
  end ln

return

method mergeSort(m = String[]) public constant binary returns String[]

  rl = String[m.length]
  al = List mergeSort(Arrays.asList(m))
  al.toArray(rl)

  return rl

method mergeSort(m = List) public constant binary returns ArrayList

  result = ArrayList(m.size)
  left   = ArrayList()
  right  = ArrayList()
  if m.size > 1 then do
    middle = m.size % 2
    loop x_ = 0 to middle - 1
      left.add(m.get(x_))
      end x_
    loop x_ = middle to m.size - 1
      right.add(m.get(x_))
      end x_
    left  = mergeSort(left)
    right = mergeSort(right)
    if (Comparable left.get(left.size - 1)).compareTo(Comparable right.get(0)) <= 0 then do
      left.addAll(right)
      result.addAll(m)
      end
    else do
      result = merge(left, right)
      end
    end
  else do
    result.addAll(m)
    end

  return result

method merge(left = List, right = List) public constant binary returns ArrayList

  result = ArrayList()
  loop label mx while left.size > 0 & right.size > 0
    if (Comparable left.get(0)).compareTo(Comparable right.get(0)) <= 0 then do
      result.add(left.get(0))
      left.remove(0)
      end
    else do
      result.add(right.get(0))
      right.remove(0)
      end
    end mx
    if left.size > 0 then do
      result.addAll(left)
      end
    if right.size > 0 then do
      result.addAll(right)
      end

  return result


proc countingSort[T](a: var openarray[T]; min, max: int) =
  let range = max - min + 1
  var count = newSeq[T](range)
  var z = 0

  for i in 0 ..< a.len: inc count[a[i] - min]

  for i in min .. max:
    for j in 0 ..< count[i - min]:
      a[z] = i
      inc z

var a = @[5, 3, 1, 7, 4, 1, 1, 20]
countingSort(a, 1, 20)
echo a


bundle Default {
  class Cocktail {
    function : Main(args : String[]) ~ Nil {
      values := [9, 7, 10, 2, 9, 7, 4, 3, 10, 2, 7, 10];
      CountingSort(values, 2, 10);
      each(i : values) {
        values[i]->PrintLine();
      };
    }

    function : CountingSort(array : Int[], min : Int, max : Int) ~ Nil {
      count := Int->New[max - min + 1];
      each(i : array) {
        number := array[i];
        v := count[number - min];
        count[number - min] := v + 1;
      };

      z := 0;
      for(i := min; i <= max; i += 1;) {
        while(count[i - min] > 0) {
          array[z] := i;
          z += 1;
          v := count[i - min]
          count[i - min] := v - 1;
        };
      };
    }
  }
}


fun quicksort [] = []
  | quicksort (x::xs) =
    let
        val (left, right) = List.partition (fn y => y<x) xs
    in
        quicksort left @ [x] @ quicksort right
    end


func quicksort<T where T : Comparable>(inout elements: [T], range: Range<Int>) {
  if (range.endIndex - range.startIndex > 1) {
    let pivotIndex = partition(&elements, range)
    quicksort(&elements, range.startIndex ..< pivotIndex)
    quicksort(&elements, pivotIndex+1 ..< range.endIndex)
  }
}

func quicksort<T where T : Comparable>(inout elements: [T]) {
  quicksort(&elements, indices(elements))
}


swap := proc(arr, a, b)
	local temp;
	temp := arr[a]:
	arr[a] := arr[b]:
	arr[b] := temp:
end proc:
newGap := proc(gap)
	local new;
	new := trunc(gap*10/13);
	if (new < 1) then return 1; end if;
	return new;
end proc;
combsort := proc(arr, len)
	local gap, swapped,i, temp;
	swapped := true:
	gap := len:
	while ((not gap = 1) or swapped) do
		gap := newGap(gap):
		swapped := false:
		for i from 1 to len-gap by 1 do
			if (arr[i] > arr[i+gap]) then
				temp := arr[i]:
				arr[i] := arr[i+gap]:
				arr[i+gap] := temp:
				swapped:= true:
			end if:
		end do:
	end do:
end proc:
arr := Array([17,3,72,0,36,2,3,8,40,0]);
combsort(arr, numelems(arr));
arr;


combSort[list_] := Module[{ gap = 0, listSize = 0, swaps = True},
        gap = listSize = Length[list];
        While[ !((gap <= 1) && (swaps == False)),

            gap = [email protected][gap, 1.25];
            If[ gap < 1, gap = 1]; i = 1; swaps = False;

            While[ ! ((i + gap - 1) >= listSize),
                If[ list[[i]] > list[[i + gap]], swaps = True;
                list[[i ;; i + gap]] = list[[i + gap ;; i ;; -1]];
                ];
            i++;
            ]
        ]
]


function list = combSort(list)

    listSize = numel(list);
    gap = int32(listSize); %Coerce gap to an int so we can use the idivide function
    swaps = true; %Swap flag

    while not((gap <= 1) && (swaps == false))

        gap = idivide(gap,1.25,'floor'); %Int divide, floor the resulting operation

        if gap < 1
            gap = 1;
        end

        i = 1; %i equals 1 because all arrays are 1 based in MATLAB
        swaps = false;

        %i + gap must be subtracted by 1 because the pseudo-code was writen
        %for 0 based arrays
        while not((i + gap - 1) >= listSize)

            if (list(i) > list(i+gap))
                list([i i+gap]) = list([i+gap i]); %swap
                swaps = true;
            end
        i = i + 1;

        end %while
    end %while
end %combSort


proc merge[T](a, b: var openarray[T]; left, middle, right: int) =
  let
    leftLen = middle - left
    rightLen = right - middle
  var
    l = 0
    r = leftLen

  for i in left ..< middle:
    b[l] = a[i]
    inc l
  for i in middle ..< right:
    b[r] = a[i]
    inc r

  l = 0
  r = leftLen
  var i = left

  while l < leftLen and r < leftLen + rightLen:
    if b[l] < b[r]:
      a[i] = b[l]
      inc l
    else:
      a[i] = b[r]
      inc r
    inc i

  while l < leftLen:
    a[i] = b[l]
    inc l
    inc i
  while r < leftLen + rightLen:
    a[i] = b[r]
    inc r
    inc i

proc mergeSort[T](a, b: var openarray[T]; left, right: int) =
  if right - left <= 1: return

  let middle = (left + right) div 2
  mergeSort(a, b, left, middle)
  mergeSort(a, b, middle, right)
  merge(a, b, left, middle, right)

proc mergeSort[T](a: var openarray[T]) =
  var b = newSeq[T](a.len)
  mergeSort(a, b, 0, a.len)

var a = @[4, 65, 2, -31, 0, 99, 2, 83, 782]
mergeSort a
echo a


let rec split_at n xs =
  match n, xs with
      0, xs ->
        [], xs
    | _, [] ->
        failwith "index too large"
    | n, x::xs when n > 0 ->
        let xs', xs'' = split_at (pred n) xs in
          x::xs', xs''
    | _, _ ->
        invalid_arg "negative argument"

let rec merge_sort cmp = function
    [] -> []
  | [x] -> [x]
  | xs ->
      let xs, ys = split_at (List.length xs / 2) xs in
        List.merge cmp (merge_sort cmp xs) (merge_sort cmp ys)

let _ =
  merge_sort compare [8;6;4;2;1;3;5;7;9]


let counting_sort_array arr lo hi =
  let count = Array.make (hi-lo+1) 0 in
    Array.iter (fun i -> count.(i-lo) <- count.(i-lo) + 1) arr;
    Array.concat (Array.to_list (Array.mapi (fun i x -> Array.make x (lo+i)) count))


function r = counting_sort(arr, minval, maxval)
  r = arr;
  z = 1;
  for i = minval:maxval
    cnt = sum(arr == i);
    while( cnt-- > 0 )
      r(z++) = i;
    endwhile
  endfor
endfunction


x : 23 : 15 : 99 : 146 : 3 : 66 : 71 : 5 : 23 : 73 : 19

quicksort param l r

   l i
   r j
   ((l+r) shr 1) k
   x.k pivot

repeat
   if pivot > x.i
      + cmp
      + i
      goif
   endif

   if pivot < x.j
      + cmp
      - j
      goif
   endif

   if i <= j
      swap x.i x.j
      - j
      + i
   endif

   if i <= j
      go repeat
   endif

   if l < j
      save l r i j
      call quicksort l j
      restore l r i j
   endif

   if i < r
      save l r i j
      call quicksort i r
      restore l r i j
   endif

   return

start

 ' original values : ' $r

 call showvalues

 call quicksort 0 10

 ' sorted values : ' $r

 call showvalues

 stop

showvalues
 $s
 i
 if i <= 10
    "$s ' ' x.i ' '" $s
    + i
    goif
 endif
 " $r $s " []

 return


fn combSort arr =
(
	local gap = arr.count
	local swaps = 1
	while not (gap == 1 and swaps == 0) do
	(
		gap = (gap / 1.25) as integer
		if gap < 1 do
		(
			gap = 1
		)
		local i = 1
		swaps = 0
		while not (i + gap > arr.count) do
		(
			if arr[i] > arr[i+gap] do
			(
				swap arr[i] arr[i+gap]
				swaps = 1
			)
			i += 1

		)

	)
	return arr
)


/* NetRexx */

options replace format comments java crossref savelog symbols binary

placesList = [String -
    "UK  London",     "US  New York"   -
  , "US  Boston",     "US  Washington" -
  , "UK  Washington", "US  Birmingham" -
  , "UK  Birmingham", "UK  Boston"     -
]
sortedList = combSort(String[] Arrays.copyOf(placesList, placesList.length))

lists = [placesList, sortedList]
loop ln = 0 to lists.length - 1
  cl = lists[ln]
  loop ct = 0 to cl.length - 1
    say cl[ct]
    end ct
    say
  end ln

return

method combSort(input = String[]) public constant binary returns String[]

  swaps = isTrue
  gap = input.length
  loop label comb until gap = 1 & \swaps
    gap = int gap / 1.25
    if gap < 1 then
      gap = 1
    i_ = 0
    swaps = isFalse
    loop label swaps until i_ + gap >= input.length
      if input[i_].compareTo(input[i_ + gap]) > 0 then do
        swap            = input[i_]
        input[i_]       = input[i_ + gap]
        input[i_ + gap] = swap
        swaps           = isTrue
        end
        i_ = i_ + 1
      end swaps
    end comb

  return input

method isTrue public constant binary returns boolean
  return 1 == 1

method isFalse public constant binary returns boolean
  return \isTrue


declare
  fun {MergeSort Xs}
     case Xs
     of nil then nil
     [] [X] then [X]
     else
        Middle = {Length Xs} div 2
        Left Right
        {List.takeDrop Xs Middle ?Left ?Right}
     in
        {List.merge {MergeSort Left} {MergeSort Right} Value.'<'}
     end
  end
in
  {Show {MergeSort [3 1 4 1 5 9 2 6 5]}}


mergeSort(v)={
  if(#v<2, return(v));
  my(m=#v\2,left=vector(m,i,v[i]),right=vector(#v-m,i,v[m+i]));
  left=mergeSort(left);
  right=mergeSort(right);
  merge(left, right)
};
merge(u,v)={
	my(ret=vector(#u+#v),i=1,j=1);
	for(k=1,#ret,
		if(i<=#u & (j>#v | u[i]<v[j]),
			ret[k]=u[i];
			i++
		,
			ret[k]=v[j];
			j++
		)
	);
	ret
};


declare
  proc {CountingSort Arr Min Max}
     Count = {Array.new Min Max 0}
     Z = {NewCell {Array.low Arr}}
  in
     %% fill frequency array
     for J in {Array.low Arr}..{Array.high Arr} do
        Number = Arr.J
     in
        Count.Number := Count.Number + 1
     end
     %% recreate array from frequencies
     for I in Min..Max do
        for C in 1..Count.I do
  	 Arr.(@Z) := I
  	 Z := @Z + 1
        end
     end
  end

  A = {Tuple.toArray unit(3 1 4 1 5 9 2 6 5)}
in
  {CountingSort A 1 9}
  {Show {Array.toRecord unit A}}


countingSort(v,mn,mx)={
  my(u=vector(#v),i=0);
  for(n=mn,mx,
    for(j=1,#v,if(v[j]==n,u[i++]=n))
  );
  u
};


program CountingSort;

procedure counting_sort(var arr : Array of Integer; n, min, max : Integer);
var
   count   : Array of Integer;
   i, j, z : Integer;
begin
   SetLength(count, max-min);
   for i := 0 to (max-min) do
      count[i] := 0;
   for i := 0 to (n-1) do
      count[ arr[i] - min ] := count[ arr[i] - min ] + 1;
   z := 0;
   for i := min to max do
      for j := 0 to (count[i - min] - 1) do begin
	 arr[z] := i;
	 z := z + 1
      end
end;

var
   ages	: Array[0..99] of Integer;
   i	: Integer;

begin
   { testing }
   for i := 0 to 99 do
      ages[i] := 139 - i;
   counting_sort(ages, 100, 0, 140);
   for i := 0 to 99 do
      writeln(ages[i]);
end.


templates quicksort
  @: [];
  $ -> #
  when <[](2..)> do
    def pivot: $(1);
    [ [ $(2..last)... -> \(
      when <..$pivot> do
        $ !
      otherwise
        ..|@quicksort: $;
     \)] -> quicksort..., $pivot, [email protected] -> quicksort... ] !
   otherwise
     $ !
end quicksort

[4,5,3,8,1,2,6,7,9,8,5] -> quicksort -> !OUT::write


proc combSort[T](a: var openarray[T]) =
  var gap = a.len
  var swapped = true
  while gap > 1 or swapped:
    gap = gap * 10 div 13
    if gap == 9 or gap == 10: gap = 11
    if gap < 1: gap = 1
    swapped = false
    var i = 0
    for j in gap ..< a.len:
      if a[i] > a[j]:
        swap a[i], a[j]
        swapped = true
      inc i

var a = @[4, 65, 2, -31, 0, 99, 2, 83, 782]
combSort a
echo a


bundle Default {
  class Stooge {
    function : Main(args : String[]) ~ Nil {
      nums := [3, 5, 1, 9, 7, 6, 8, 2, 4];
      CombSort(nums);
      each(i : nums) {
        IO.Console->Print(nums[i])->Print(",");
      };
      IO.Console->PrintLine();
    }

    function : CombSort(input : Int[]) ~ Nil {
      gap : Float := input->Size();
      swaps := true;
      while(gap > 1 | swaps) {
        gap /= 1.247330950103979;
        if(gap < 1) { gap := 1; };
        i : Int := 0;
        swaps := false;
        while(i + gap < input->Size()) {
          igap : Int := i + gap->As(Int);
          if (input[i] > input[igap]) {
            swap : Int := input[i];
            input[i] := input[igap];
            input[igap] := swap;
            swaps := true;
          };
          i += 1;
        };
      };
    }
  }
}


program MergeSortDemo;

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}

type
  TIntArray = array of integer;

function merge(left, right: TIntArray): TIntArray;
  var
    i, j: integer;
  begin
    j := 0;
    setlength(Result, length(left) + length(right));
    while (length(left) > 0) and (length(right) > 0) do
    begin
      if left[0] <= right[0] then
      begin
	Result[j] := left[0];
	inc(j);
	for i := low(left) to high(left) - 1 do
	  left[i] := left[i+1];
	setlength(left, length(left) - 1);
      end
      else
      begin
	Result[j] := right[0];
	inc(j);
	for i := low(right) to high(right) - 1 do
	  right[i] := right[i+1];
	setlength(right, length(right) - 1);
      end;
    end;
    if length(left) > 0 then
      for i := low(left) to high(left) do
	  Result[j + i] := left[i];
    j := j + length(left);
    if length(right) > 0 then
      for i := low(right) to high(right) do
	  Result[j + i] := right[i];
  end;

function mergeSort(m: TIntArray): TIntArray;
  var
    left, right: TIntArray;
    i, middle: integer;
  begin
    setlength(Result, length(m));
    if length(m) = 1 then
      Result[0] := m[0]
    else if length(m) > 1 then
    begin
      middle := length(m) div 2;
      setlength(left, middle);
      setlength(right, length(m)-middle);
      for i := low(left) to high(left) do
        left[i] := m[i];
      for i := low(right) to high(right) do
        right[i] := m[middle+i];
      left  := mergeSort(left);
      right := mergeSort(right);
      Result := merge(left, right);
    end;
  end;

var
  data: TIntArray;
  i: integer;

begin
  setlength(data, 8);
  Randomize;
  writeln('The data before sorting:');
  for i := low(data) to high(data) do
  begin
    data[i] := Random(high(data));
    write(data[i]:4);
  end;
  writeln;
  data := mergeSort(data);
  writeln('The data after sorting:');
  for i := low(data) to high(data) do
  begin
    write(data[i]:4);
  end;
  writeln;
end.


#! /usr/bin/perl
use strict;

sub counting_sort
{
    my ($a, $min, $max) = @_;

    my @cnt = (0) x ($max - $min + 1);
    $cnt[$_ - $min]++ foreach @$a;

    my $i = $min;
    @$a = map {($i++) x $_} @cnt;
}


with javascript_semantics

function countingSort(sequence array, integer mina, maxa)
    sequence count = repeat(0,maxa-mina+1)
    array = deep_copy(array)
    for i=1 to length(array) do
        count[array[i]-mina+1] += 1
    end for
    integer z = 1
    for i=mina to maxa do
        for j=1 to count[i-mina+1] do
            array[z] := i
            z += 1
        end for
    end for
    return array
end function

sequence s = {5, 3, 1, 7, 4, 1, 1, 20}
?countingSort(s,min(s),max(s))


package require Tcl 8.5

proc quicksort {m} {
    if {[llength $m] <= 1} {
        return $m
    }
    set pivot [lindex $m 0]
    set less [set equal [set greater [list]]]
    foreach x $m {
        lappend [expr {$x < $pivot ? "less" : $x > $pivot ? "greater" : "equal"}] $x
    }
    return [concat [quicksort $less] $equal [quicksort $greater]]
}

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


let comb_sort ~input =
  let input_length = Array.length input in
  let gap = ref(input_length) in
  let swapped = ref true in
  while (!gap > 1 || !swapped) do
    if (!gap > 1) then
      gap := int_of_float (float !gap /. 1.3);

    swapped := false;
    for i = 0 to input_length - !gap do
      if input.(i) > input.(i + !gap) then begin
        let tmp = input.(i) in
        input.(i) <- input.(i + !gap);
        input.(i + !gap) <- tmp;
        swapped := true;
      end
    done
  done
;;


declare
  proc {CombSort Arr}
     Low = {Array.low Arr}
     High = {Array.high Arr}
     Size = High - Low + 1
     Gap = {NewCell Size}
     Swapped = {NewCell true}
     proc {Swap I J}
        Arr.J := (Arr.I := Arr.J)
     end
  in
     for while:@Gap>1 orelse @Swapped do
        if @Gap > 1 then
           Gap := {Float.toInt {Floor {Int.toFloat @Gap} / 1.3}}
        end
        Swapped := false
        for I in Low..High[email protected]Gap do
           if Arr.I > Arr.(I[email protected]Gap) then
              {Swap I I[email protected]Gap}
              Swapped := true
           end
        end
     end
  end
  Arr = {Tuple.toArray unit(3 1 4 1 5 9 2 6 5)}
in
  {CombSort Arr}
  {Show {Array.toRecord unit Arr}}


<?php

function counting_sort(&$arr, $min, $max)
{
  $count = array();
  for($i = $min; $i <= $max; $i++)
  {
    $count[$i] = 0;
  }

  foreach($arr as $number)
  {
    $count[$number]++;
  }
  $z = 0;
  for($i = $min; $i <= $max; $i++) {
    while( $count[$i]-- > 0 ) {
      $arr[$z++] = $i;
    }
  }
}


(de countingSort (Lst Min Max)
   (let Count (need (- Max Min -1) 0)
      (for N Lst
         (inc (nth Count (- N Min -1))) )
      (make
         (map
            '((C I)
               (do (car C) (link (car I))) )
            Count
            (range Min Max) ) ) ) )


count_sort: procedure (A);
   declare A(*) fixed;
   declare (min, max) fixed;
   declare i fixed binary;

   max, min = A(lbound(A,1));
   do i = 1 to hbound(A,1);
       if max < A(i) then max = A(i);
       if min > A(i) then min = A(i);
   end;

   begin;
      declare t(min:max) fixed;
      declare (i, j, k) fixed binary (31);
      t = 0;
      do i = 1 to hbound(A,1);
         j = A(i);
         t(j) = t(j) + 1;
      end;
      k = lbound(A,1);
      do i = min to max;
         if t(i) ^= 0 then
            do j = 1 to t(i);
               A(k) = i;
               k = k + 1;
            end;
      end;
   end;
end count_sort;


/**
  Generic quicksort function using typescript generics.
  Follows quicksort as done in CLRS.
*/
export type Comparator<T> = (o1: T, o2: T) => number;

export function quickSort<T>(array: T[], compare: Comparator<T>) {
  if (array.length <= 1 || array == null) {
    return;
  }
  sort(array, compare, 0, array.length - 1);
}

function sort<T>(
    array: T[], compare: Comparator<T>, low: number, high: number) {
  if (low < high) {
    const partIndex = partition(array, compare, low, high);
    sort(array, compare, low, partIndex - 1);
    sort(array, compare, partIndex + 1, high);
  }
}

function partition<T>(
    array: T[], compare: Comparator<T>, low: number, high: number): number {
  const pivot: T = array[high];
  let i: number = low - 1;
  for (let j = low; j <= high - 1; j++) {
    if (compare(array[j], pivot) == -1) {
      i = i + 1;
      swap(array, i, j)
    }
  }
  if (compare(array[high], array[i + 1]) == -1) {
    swap(array, i + 1, high);
  }
  return i + 1;
}

function swap<T>(array: T[], i: number, j: number) {
  const newJ: T = array[i];
  array[i] = array[j];
  array[j] = newJ;
}

export function testQuickSort(): void {
  function numberComparator(o1: number, o2: number): number {
    if (o1 < o2) {
      return -1;
    } else if (o1 == o2) {
      return 0;
    }
    return 1;
  }
  let tests: number[][] = [
    [], [1], [2, 1], [-1, 2, -3], [3, 16, 8, -5, 6, 4], [1, 2, 3, 4, 5, 6],
    [1, 2, 3, 4, 5]
  ];

  for (let testArray of tests) {
    quickSort(testArray, numberComparator);
    console.log(testArray);
  }
}


combSort(v)={
  my(phi=(1+sqrt(5))/2,magic=1/(1-exp(-phi)),g=#v,swaps);
  while(g>1 | swaps,
    if(g>1, g\=magic);
    swaps=0;
    for(i=1,#v-g,
      if(v[i]>v[i+g],
        my(t=v[i]);
        v[i]=v[i+g];
        v[i+g]=t;
        swaps++
      )
    )
  );
  v
};


program CombSortDemo;

// NOTE: The array is 1-based
//       If you want to use this code on a 0-based array, see below
type
  TIntArray = array[1..40] of integer;

var
  data: TIntArray;
  i: integer;

procedure combSort(var a: TIntArray);
  var
    i, gap, temp: integer;
    swapped: boolean;
  begin
    gap := length(a);
    swapped := true;
    while (gap > 1) or swapped do
    begin
      gap := trunc(gap / 1.3);
      if (gap < 1) then
        gap := 1;
      swapped := false;
      for i := 1 to length(a) - gap do
        if a[i] > a[i+gap] then
        begin
	  temp := a[i];
          a[i] := a[i+gap];
          a[i+gap] := temp;
          swapped := true;
        end;
    end;
  end;

begin
  Randomize;
  writeln('The data before sorting:');
  for i := low(data) to high(data) do
  begin
    data[i] := Random(high(data));
    write(data[i]:4);
  end;
  writeln;
  combSort(data);
  writeln('The data after sorting:');
  for i := low(data) to high(data) do
  begin
    write(data[i]:4);
  end;
  writeln;
end.


with javascript_semantics

function merge(sequence left, sequence right)
sequence result = {}
    while length(left)>0 and length(right)>0 do
        if left[1]<=right[1] 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)
    if length(m)<=1 then return m end if
    integer middle = floor(length(m)/2)
    sequence left = mergesort(m[1..middle]),
            right = mergesort(m[middle+1..$])
    if left[$]<=right[1] then
        return left & right
    elsif right[$]<=left[1] then
        return right & left
    end if
    return merge(left, right)
end function

constant s = shuffle(tagset(10))
? s
? mergesort(deep_copy(s))


function countingSort($array) {
    $minmax = $array | Measure-Object -Minimum -Maximum
    $min, $max = $minmax.Minimum, $minmax.Maximum
    $count = @(0) * ($max - $min  + 1)
    foreach ($number in $array) {
        $count[$number - $min] = $count[$number - $min] + 1
    }
    $z = 0
    foreach ($i in $min..$max) {
        while (0 -lt $count[$i - $min]) {
            $array[$z] = $i
            $z = $z+1
            $count[$i - $min] = $count[$i - $min] - 1
        }
    }
    $array
}

$array = foreach ($i in 1..50) {Get-Random -Minimum 0 -Maximum 26}
"$array"
"$(countingSort $array)"


Procedure Counting_sort(Array data_array(1), min, max)
  Define i, j
  Dim c(max - min)

  For i = 0 To ArraySize(data_array())
    c(data_array(i) - min) + 1
  Next

  For i = 0 To ArraySize(c())
    While c(i)
      data_array(j) = i + min
      j + 1
      c(i) - 1
    Wend
  Next
EndProcedure


PRINT "Quick sort:"
  n = FUNC (_InitArray)
  PROC _ShowArray (n)
  PROC _Quicksort (n)
  PROC _ShowArray (n)
PRINT

END

_InnerQuick PARAM(2)
  LOCAL(4)

  IF [email protected] < 2 THEN RETURN
  [email protected] = [email protected] + [email protected] - 1
  [email protected] = [email protected]
  [email protected] = [email protected]
  [email protected] = @(([email protected] + [email protected]) / 2)

  DO
    DO WHILE @([email protected]) < [email protected]
      [email protected] = [email protected] + 1
    LOOP

    DO WHILE @([email protected]) > [email protected]
      [email protected] = [email protected] - 1
    LOOP

    IF [email protected] - 1 < [email protected] THEN
      PROC _Swap ([email protected], [email protected])
      [email protected] = [email protected] + 1
      [email protected] = [email protected] - 1
    ENDIF

    UNTIL [email protected] > [email protected]
  LOOP

  IF [email protected] < [email protected] THEN PROC _InnerQuick ([email protected], [email protected] - [email protected] + 1)
  IF [email protected] < [email protected] THEN PROC _InnerQuick ([email protected], [email protected] - [email protected] + 1)
RETURN

_Quicksort PARAM(1)                   ' Quick sort
  PROC _InnerQuick (0, [email protected])
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 combSort {
    my @arr = @_;
    my $gap = @arr;
    my $swaps = 1;
    while ($gap > 1 || $swaps) {
        $gap /= 1.25 if $gap > 1;
        $swaps = 0;
        foreach my $i (0 .. $#arr - $gap) {
            if ($arr[$i] > $arr[$i+$gap]) {
                @arr[$i, $i+$gap] = @arr[$i+$gap, $i];
                $swaps = 1;
            }
        }
    }
    return @arr;
}


with javascript_semantics

function comb_sort(sequence s)
integer gap = length(s)-1
    while 1 do
        gap = max(floor(gap/1.3),1)
        integer swapped = 0
        for i=1 to length(s)-gap do
            object si = s[i]
            if si>s[i+gap] then
                s[i] = s[i+gap]
                s[i+gap] = si
                swapped = 1
            end if
        end for
        if gap=1 and swapped=0 then exit end if
    end while
    return s
end function

?comb_sort(shuffle(tagset(10)))


function mergesort($arr){
	if(count($arr) == 1 ) return $arr;
	$mid = count($arr) / 2;
    $left = array_slice($arr, 0, $mid);
    $right = array_slice($arr, $mid);
	$left = mergesort($left);
	$right = mergesort($right);
	return merge($left, $right);
}

function merge($left, $right){
	$res = array();
	while (count($left) > 0 && count($right) > 0){
		if($left[0] > $right[0]){
			$res[] = $right[0];
			$right = array_slice($right , 1);
		}else{
			$res[] = $left[0];
			$left = array_slice($left, 1);
		}
	}
	while (count($left) > 0){
		$res[] = $left[0];
		$left = array_slice($left, 1);
	}
	while (count($right) > 0){
		$res[] = $right[0];
		$right = array_slice($right, 1);
	}
	return $res;
}

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


>>> from collections import defaultdict
>>> def countingSort(array, mn, mx):
	count = defaultdict(int)
	for i in array:
		count[i] += 1
	result = []
	for j in range(mn,mx+1):
		result += [j]* count[j]
	return result

>>> data = [9, 7, 10, 2, 9, 7, 4, 3, 10, 2, 7, 10, 2, 1, 3, 8, 7, 3, 9, 5, 8, 5, 1, 6, 3, 7, 5, 4, 6, 9, 9, 6, 6, 10, 2, 4, 5, 2, 8, 2, 2, 5, 2, 9, 3, 3, 5, 7, 8, 4]
>>> mini,maxi = 1,10
>>> countingSort(data, mini, maxi) == sorted(data)
True


  [ 2dup peek 1+
    unrot poke ]          is [1+]  (   [ n --> [ )

  [ 1+ dip tuck -
    rot 0 swap of
    swap rot witheach
      [ over +
        rot swap [1+]
        swap ]
    negate swap
    [] swap witheach
      [ dip [ over i^ + ]
        of join ]
     nip ]                is csort ( [ n n --> [ )

  [] 15 times
    [ 10 random 10 + join ]

  dup say "Before: " echo cr
  10 19 csort
  say "After:  " echo


split() {
  (while read n ; do
      test $1 -gt $n && echo $n > $2 || echo $n > $3
  done)
}

qsort() {
 (read p; test -n "$p" && (
     lc="1.$1" ; gc="2.$1"
     split $p >(qsort $lc >$lc) >(qsort $gc >$gc);
     cat $lc <(echo $p) $gc
     rm -f $lc $gc;
 ))
}

cat to.sort | qsort


function combSort($arr){
	$gap = count($arr);
        $swap = true;
	while ($gap > 1 || $swap){
		if($gap > 1) $gap /= 1.25;

		$swap = false;
		$i = 0;
		while($i+$gap < count($arr)){
			if($arr[$i] > $arr[$i+$gap]){
				list($arr[$i], $arr[$i+$gap]) = array($arr[$i+$gap],$arr[$i]);
				$swap = true;
			}
			$i++;
		}
	}
	return $arr;
}


(de combSort (Lst)
   (let (Gap (length Lst)  Swaps NIL)
      (while (or (> Gap 1) Swaps)
         (setq Gap (max 1 (/ (* Gap 4) 5)))
         (off Swaps)
         (use Lst
            (for (G (cdr (nth Lst Gap))  G  (cdr G))
               (when (> (car Lst) (car G))
                  (xchg Lst G)
                  (on Swaps) )
               (pop 'Lst) ) ) ) )
   Lst )


% True if S is a sorted copy of L, using merge sort
msort([],[]).
msort([X],[X]).
msort(U,S) :-
  split(U, L, R),
  msort(L, SL),
  msort(R, SR),
  merge(SL, SR, S).

% split(LIST,L,R)
% Alternate elements of LIST in L and R
split([],[],[]).
split([X],[X],[]).
split([L,R|T],[L|LT],[R|RT]) :-
  split( T, LT, RT ).

% merge( LS, RS, M )
% Assuming LS and RS are sorted, True if M is the sorted merge of the two
merge([],RS,RS).
merge(LS,[],LS).
merge([L|LS],[R|RS],[L|T]) :-
    L @=< R,
    merge(LS,[R|RS],T).
merge([L|LS],[R|RS],[R|T]) :-
    L @> R,
    merge([L|LS],RS,T).