Sorting algorithms/Radix sort

Revision as of 21:59, 11 June 2012 by rosettacode>Gerard Schildberger (→‎{{header|REXX}}: added the REXX language. -- ~~~~)

In this task, the goal is to sort an integer array with the radix sort algorithm. The primary purpose is to complete the characterization of sort algorithms task.

Task
Sorting algorithms/Radix sort
You are encouraged to solve this task according to the task description, using any language you may know.

Ada

radix_sort.adb: <lang Ada>with Ada.Text_IO; procedure Radix_Sort is

  type Integer_Array is array (Positive range <>) of Integer;
  procedure Least_Significant_Radix_Sort (Data : in out Integer_Array; Base : Positive := 10) is
     type Bucket is record
        Count   : Natural := 0;
        Content : Integer_Array (Data'Range);
     end record;
     subtype Bucket_Index is Integer range -Base + 1 .. Base - 1;
     type Bucket_Array is array (Bucket_Index) of Bucket;
     procedure Append (To : in out Bucket; Item : Integer) is
     begin
        To.Count := To.Count + 1;
        To.Content (To.Count) := Item;
     end Append;
     function Get_Nth_Digit (Value : Integer; N : Positive) return Integer is
        Result : Integer := (Value / (Base ** (N - 1))) mod Base;
     begin
        if Value < 0 then
           Result := -Result;
        end if;
        return Result;
     end Get_Nth_Digit;
     function Get_Maximum return Natural is
        Result : Natural := 0;
     begin
        for I in Data'Range loop
           if abs (Data (I)) > Result then
              Result := abs (Data (I));
           end if;
        end loop;
        return Result;
     end Get_Maximum;
     function Split (Pass : Positive) return Bucket_Array is
        Buckets : Bucket_Array;
     begin
        for I in Data'Range loop
           Append (To   => Buckets (Get_Nth_Digit (Data (I), Pass)),
                   Item => Data (I));
        end loop;
        return Buckets;
     end Split;
     function Merge (Buckets : Bucket_Array) return Integer_Array is
        Result        : Integer_Array (Data'Range);
        Current_Index : Positive := 1;
     begin
        for Sublist in Buckets'Range loop
           for Item in 1 .. Buckets (Sublist).Count loop
              Result (Current_Index) := Buckets (Sublist).Content (Item);
              Current_Index := Current_Index + 1;
           end loop;
        end loop;
        return Result;
     end Merge;
     Max_Number  : Natural := Get_Maximum;
     Digit_Count : Positive := 1;
  begin
     -- count digits of biggest number
     while Max_Number > Base loop
        Digit_Count := Digit_Count + 1;
        Max_Number := Max_Number / Base;
     end loop;
     for Pass in 1 .. Digit_Count loop
        Data := Merge (Split (Pass));
     end loop;
  end Least_Significant_Radix_Sort;
  Test_Array : Integer_Array := (170, 45, 75, -90, -802, 24, 2, 66);

begin

  Least_Significant_Radix_Sort (Test_Array, 4);
  for I in Test_Array'Range loop
     Ada.Text_IO.Put (Integer'Image (Test_Array (I)));
  end loop;
  Ada.Text_IO.New_Line;

end Radix_Sort;</lang>

output:

-802-90 2 24 45 66 75 170

C

Radix sort, "digits" are most significant bits.<lang c>#include <stdio.h>

  1. include <limits.h>
  2. include <stdlib.h>

typedef unsigned uint;

  1. define swap(a, b) { tmp = a; a = b; b = tmp; }
  2. define each(i, x) for (i = 0; i < x; i++)

/* sort unsigned ints */ static void rad_sort_u(uint *from, uint *to, uint bit) { if (!bit || to < from + 1) return;

uint *ll = from, *rr = to - 1, tmp; while (1) { /* find left most with bit, and right most without bit, swap */ while (ll < rr && !(*ll & bit)) ll++; while (ll < rr && (*rr & bit)) rr--; if (ll >= rr) break; swap(*ll, *rr); }

if (!(bit & *ll) && ll < to) ll++; bit >>= 1;

rad_sort_u(from, ll, bit); rad_sort_u(ll, to, bit); }

/* sort signed ints: flip highest bit, sort as unsigned, flip back */ static void radix_sort(int *a, const size_t len) { size_t i; uint *x = (uint*) a;

each(i, len) x[i] ^= INT_MIN; rad_sort_u(x, x + len, INT_MIN); each(i, len) x[i] ^= INT_MIN; }

static inline void radix_sort_unsigned(uint *a, const size_t len) { rad_sort_u(a, a + len, (uint)INT_MIN); }

int main(void) { int len = 16, x[16], i; size_t len = 16, i; each(i, len) x[i] = rand() % 512 - 256;

radix_sort(x, len);

each(i, len) printf("%d%c", x[i], i + 1 < len ? ' ' : '\n');

return 0;

}</lang>output

-182 -175 -151 -141 -70 -51 -20 -5 -1 41 70 103 171 198 227 242

C++

Implements a least significant digit radix sort and a recursive most significant digit radix sort.

Note: the LSD radix sort uses the standard library std::stable_partition algorithm. This algorithm is guaranteed to preserve relative order and has a higher runtime cost. The MSD radix sort uses std::partition and can be significantly faster. <lang cpp>#include <algorithm>

  1. include <iostream>
  2. include <iterator>

// Radix sort comparator for 32-bit two's complement integers class radix_test {

   const int bit; // bit position [0..31] to examine

public:

   radix_test(int offset) : bit(offset) {} // constructor
   bool operator()(int value) const // function call operator
   {
       if (bit == 31) // sign bit
           return value < 0; // negative int to left partition
       else
           return !(value & (1 << bit)); // 0 bit to left partition
   }

};

// Least significant digit radix sort void lsd_radix_sort(int *first, int *last) {

   for (int lsb = 0; lsb < 32; ++lsb) // least-significant-bit
   {
       std::stable_partition(first, last, radix_test(lsb));
   }

}

// Most significant digit radix sort (recursive) void msd_radix_sort(int *first, int *last, int msb = 31) {

   if (first != last && msb >= 0)
   {
       int *mid = std::partition(first, last, radix_test(msb));
       msb--; // decrement most-significant-bit
       msd_radix_sort(first, mid, msb); // sort left partition
       msd_radix_sort(mid, last, msb); // sort right partition
   }

}

// test radix_sort int main() {

   int data[] = { 170, 45, 75, -90, -802, 24, 2, 66 };
   lsd_radix_sort(data, data + 8);
   // msd_radix_sort(data, data + 8);
   std::copy(data, data + 8, std::ostream_iterator<int>(std::cout, " "));
   return 0;

}</lang> Output:

-802 -90 2 24 45 66 75 170 

D

Shorter Version

<lang d>import std.stdio, std.math, std.traits, std.range, std.algorithm;

ElementType!R[] radixSort(size_t N=10, R)(R r) if (hasLength!R && isRandomAccessRange!R &&

   isIntegral!(ElementType!R)) {
   alias ElementType!R E;
   static if (isDynamicArray!R)
       alias r res;         // input is array => in place sort
   else
       E[] res = r.array(); // input is Range => return a new array
   E absMax = r.map!abs().reduce!max();
   immutable nPasses = 1 + cast(int)(log(absMax) / log(N));
   foreach (pass; 0 .. nPasses) {
       auto bucket = new E[][](2 * N - 1, 0);
       foreach (v; res) {
           int bIdx = abs(v / (N ^^ pass)) % N;
           bIdx = (v < 0) ? -bIdx : bIdx;
           bucket[N + bIdx - 1] ~= v;
       }
       res = bucket.join();
   }
   return res;

}

void main() {

   auto items = [170, 45, 75, -90, 2, 24, -802, 66];
   items.radixSort().writeln();
   items.map!q{1 - a}().radixSort().writeln();

}</lang>

Output:
[-802, -90, 2, 24, 45, 66, 75, 170]
[-1, -23, -44, -65, -74, -169, 91, 803]

More Efficient Version

<lang d>import std.array, std.traits;

extern(C) void* alloca(in size_t length) pure nothrow;

void radixSort(size_t MAX_ALLOCA=5_000, U)(U[] data) /*pure nothrow*/ if (isUnsigned!U) {

   static void radix(in uint byteIndex, in U[] source, U[] dest)
   pure nothrow {
       immutable size_t sourceSize = source.length;
       ubyte* curByte = (cast(ubyte*)source.ptr) + byteIndex;
       uint[256] byteCounter;
       for (size_t i = 0; i < sourceSize; i++, curByte += U.sizeof)
           byteCounter[*curByte]++;
       {
           uint indexStart;
           foreach (uint i; 0 .. byteCounter.length) {
               immutable size_t tempCount = byteCounter[i];
               byteCounter[i] = indexStart;
               indexStart += tempCount;
           }
       }
       curByte = (cast(ubyte*)source.ptr) + byteIndex;
       for (size_t i = 0; i < sourceSize; i++, curByte += U.sizeof) {
           uint* countPtr = byteCounter.ptr + *curByte;
           dest[*countPtr] = source[i];
           (*countPtr)++;
       }
   }
   U[] tempData;
   if (U.sizeof * data.length <= MAX_ALLOCA) {
       U* ptr = cast(U*)alloca(data.length * U.sizeof);
       if (ptr != null)
           tempData = ptr[0 .. data.length];
   }
   if (tempData.empty) // Not pure, not nothrow.
       tempData = uninitializedArray!(U[])(data.length);
   static if (U.sizeof == 1) {
       radix(0, data, tempData);
       data[] = tempData[];
   } else {
       for (uint i = 0; i < U.sizeof; i += 2) {
           radix(i + 0, data, tempData);
           radix(i + 1, tempData, data);
       }
   }

}

void main() {

   import std.stdio;
   uint[] items = [170, 45, 75, 4294967206, 2, 24, 4294966494, 66];
   items.radixSort();
   writeln(items);

}</lang>

Output:
[2, 24, 45, 66, 75, 170, 4294966494, 4294967206]

Original C++ code, modified (unknown license), by Andre Reinald, Paul Harris, Ryan Rohrer, Dirk Jagdmann: http://www.cubic.org/docs/download/radix_ar_2011.cpp

Go

LSD radix 256, negatives handled by flipping the high bit. <lang go>package main

import (

   "bytes"
   "encoding/binary"
   "fmt"

)

// declarations for word size of data type word int32 const wordLen = 4 const highBit = -1 << 31

var data = []word{170, 45, 75, -90, -802, 24, 2, 66}

func main() {

   buf := bytes.NewBuffer(nil)
   ds := make([][]byte, len(data))
   for i, x := range data {
       binary.Write(buf, binary.LittleEndian, x^highBit)
       b := make([]byte, wordLen)
       buf.Read(b)
       ds[i] = b
   }
   bins := make([][][]byte, 256)
   for i := 0; i < wordLen; i++ {
       for _, b := range ds {
           bins[b[i]] = append(bins[b[i]], b)
       }
       j := 0
       for k, bs := range bins {
           copy(ds[j:], bs)
           j += len(bs)
           bins[k] = bs[:0]
       }
   }
   fmt.Println("original:", data)
   var w word
   for i, b := range ds {
       buf.Write(b)
       binary.Read(buf, binary.LittleEndian, &w)
       data[i] = w^highBit
   }
   fmt.Println("sorted:  ", data)

}</lang> Output:

original: [170 45 75 -90 -802 24 2 66]
sorted:   [-802 -90 2 24 45 66 75 170]

Groovy

This solution assumes the radix is a power of 2: <lang groovy>def radixSort = { final radixExponent, list ->

   def fromBuckets = new TreeMap([0:list])
   def toBuckets = new TreeMap()
   final radix = 2**radixExponent
   final mask = radix - 1
   final radixDigitSize = (int)Math.ceil(64/radixExponent)
   final digitWidth = radixExponent
   (0..<radixDigitSize).each { radixDigit ->
       fromBuckets.values().findAll { it != null }.flatten().each {
           print '.'
           long bucketNumber = (long)((((long)it) >>> digitWidth*radixDigit) & mask)
           toBuckets[bucketNumber] = toBuckets[bucketNumber] ?: []
           toBuckets[bucketNumber] << it
       }
       (fromBuckets, toBuckets) = [toBuckets, fromBuckets]
       toBuckets.clear()
   }
   final overflow = 2**(63 % radixExponent)
   final pos = {it < overflow}
   final neg = {it >= overflow}
   final keys = fromBuckets.keySet()
   final twosComplIndx = [] + (keys.findAll(neg)) + (keys.findAll(pos))
   twosComplIndx.collect { fromBuckets[it] }.findAll { it != null }.flatten()

}</lang>

Test: <lang groovy>println (radixSort(3, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(3, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(3, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(8, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(8, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(8, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(11, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(11, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(11, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(16, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(16, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(16, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(32, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(32, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(32, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4]))</lang>

Output:

..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

........................................................................................................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
........................................................................................................................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
........................................................................................................................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

..............................................................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
..........................................................................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
..........................................................................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

....................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
............................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
............................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

..........................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
..............................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
..............................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

Haskell

<lang haskell>import Data.Bits (Bits(testBit, bitSize)) import Data.List (partition)

lsdSort :: (Ord a, Bits a) => [a] -> [a] lsdSort = fixSort positiveLsdSort

msdSort :: (Ord a, Bits a) => [a] -> [a] msdSort = fixSort positiveMsdSort

-- Fix a sort that puts negative numbers at the end, like positiveLsdSort and positiveMsdSort fixSort sorter list = uncurry (flip (++)) (break (< 0) (sorter list))

positiveLsdSort :: (Bits a) => [a] -> [a] positiveLsdSort list = foldl step list [0..bitSize (head list)] where step list bit = uncurry (++) (partition (not . flip testBit bit) list)

positiveMsdSort :: (Bits a) => [a] -> [a] positiveMsdSort list = aux (bitSize (head list) - 1) list where aux _ [] = [] aux (-1) list = list aux bit list = aux (bit - 1) lower ++ aux (bit - 1) upper where (lower, upper) = partition (not . flip testBit bit) list</lang>

J

Generally, this task should be accomplished in J using /:~. Here we take an approach that's more comparable with the other examples on this page.

keys f/. data evaluates the function f on each group of data at the same position as similar keys. Sorting requires ordered keys. This code uses a J idiom: prepend the keys and matching data. The extra data is removed by behead }..

<lang j> radixSortR =: 3 : 0 NB. base radixSort data 16 radixSortR y

keys =. x #.^:_1 y NB. compute keys length =. #{.keys extra =. (-length) {."0 buckets =. i.x for_pass. i.-length do.

  keys =. ; (buckets,pass{"1 keys) <@:}./.extra,keys

end. x#.keys NB. restore the data )</lang>

An alternate implementation is <lang j>radixsort=: (] #~ [: +/ =/) i.@(>./)</lang>

This uses the maximum value of the list for the base, which allows the list to be sorted in one pass.

Example use:

<lang j> radixsort ?.@#~10 4 5 6 6 6 6 6 8 8</lang>

Or, for negative number support:

<lang j>rsort=: (] + radixsort@:-) <./</lang>

Example:

<lang j> rsort _6+?.@#~10 _2 _1 0 0 0 0 0 2 2</lang>

PicoLisp

This is a LSD base-2 radix sort using queues: <lang PicoLisp>(de radixSort (Lst)

  (let Mask 1
     (while
        (let (Pos (list NIL NIL)  Neg (list NIL NIL)  Flg)
           (for N Lst
              (queue
                 (if2 (ge0 N) (bit? Mask N)
                    (cdr Pos) Pos Neg (cdr Neg) )
                 N )
              (and (>= (abs N) Mask) (on Flg)) )
           (setq
              Lst (conc (apply conc Neg) (apply conc Pos))
              Mask (* 2 Mask) )
           Flg ) ) )
  Lst )</lang>

Output:

: (radixSort (make (do 12 (link (rand -999 999)))))
-> (-999 -930 -666 -336 -218 68 79 187 391 405 697 922)

PureBasic

<lang PureBasic>Structure bucket

 List i.i()

EndStructure

DataSection

 ;sets specify the size (1 based) followed by each integer
 set1:
 Data.i 10 ;size
 Data.i 1, 3, 8, 9, 0, 0, 8, 7, 1, 6 ;data
 set2:
 Data.i 8 
 Data.i 170, 45, 75, 90, 2, 24, 802, 66
 set3:
 Data.i 8
 Data.i 170, 45, 75, 90, 2, 24, -802, -66

EndDataSection

Procedure setIntegerArray(Array x(1), *setPtr)

 Protected i, count
 count = PeekI(*setPtr) - 1 ;convert to zero based count
 *setPtr + SizeOf(Integer) ;move pointer forward to data
 Dim x(count)
 For i = 0 To count
   x(i) = PeekI(*setPtr + i * SizeOf(Integer))
 Next 

EndProcedure

Procedure displayArray(Array x(1))

 Protected i, Size = ArraySize(x())
 For i = 0 To Size
   Print(Str(x(i)))
   If i < Size: Print(", "): EndIf
 Next 
 PrintN("")

EndProcedure

Procedure radixSort(Array x(1), Base = 10)

 Protected count = ArraySize(x())
 If Base < 1 Or count < 1: ProcedureReturn: EndIf ;exit due to invalid values
 
 Protected i, pv, digit, digitCount, maxAbs, pass, index
 ;find element with largest number of digits
 For i = 0 To count
   If Abs(x(i)) > maxAbs
     maxAbs = Abs(x(i))
   EndIf 
 Next
 
 digitCount = Int(Log(maxAbs)/Log(Base)) + 1
 
 For pass = 1 To digitCount
   Dim sortBuckets.bucket(Base * 2 - 1)
   pv = Pow(Base, pass - 1)
   
   ;place elements in buckets according to the current place-value's digit
   For index = 0 To count
     digit = Int(x(index)/pv) % Base + Base
     AddElement(sortBuckets(digit)\i())
     sortBuckets(digit)\i() = x(index)
   Next
   
   ;transfer contents of buckets back into array
   index = 0
   For digit = 1 To (Base * 2) - 1
     ForEach sortBuckets(digit)\i()
       x(index) = sortBuckets(digit)\i()
       index + 1
     Next 
   Next
 Next

EndProcedure

If OpenConsole()

 Dim x(0)
 setIntegerArray(x(), ?set1)
 radixSort(x()): displayArray(x())
 
 setIntegerArray(x(), ?set2)
 radixSort(x()): displayArray(x())
 
 setIntegerArray(x(), ?set3)
 radixSort(x(), 2): displayArray(x())
 
 Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
 CloseConsole()

EndIf</lang> Sample output:

0, 0, 1, 1, 3, 6, 7, 8, 8, 9
2, 24, 45, 66, 75, 90, 170, 802
-802, -66, 2, 24, 45, 75, 90, 170

Python

This example is incorrect. Please fix the code and remove this message.

Details: Doesn't handle negative integers.

The wikipedia article cited in the introduction includes a python implementation of LSB radix sort.

REXX

<lang rexx>/*REXX program performs a radix sort on an integer array. */ aList='0 2 3 4 5 5 7 6 6 7 11 7 13 9 8 8 17 8 19 9 10 13 23 9 10 15 9 11',

     '29 10 31 10 14 19 12 10 37 21 16 11 41 12 43 15 11 25 47 11 14 12',
     '20 17 53 11 16 13 22 31 59 12 61 33 13 12 18 16 67 21 26 14 71 12',
     '73 39 13 23 18 18 79 13 12 43 83 14 22 45 32 17 89 13 20 27 34 49',
     '24 13 97 16 17 14 101 22 103 19 15 55 107 13 109 18 40 15 113 -42'

/*excluding -42, the abbreviated list is called the integer log function*/

mina=word(aList,1); maxa=mina

    do n=1 for words(aList); x=word(aList,n); @.n=x   /*list ──> array.*/
    mina=min(x,mina);  maxa=max(x,maxa)
    width=max(length(abs(mina)),length(maxa))
    end

n=words(aList) w=length(n) call radSort n

               do j=1 for n
               say 'item' right(j,w) "after the radix sort:" right(@.j,width+1)
               end

exit /*───────────────────────────────────RADSORT subroutine─────────────────*/ radSort: procedure expose @. width; parse arg size; mote=c2d(' '); #=1 !.#._b=1 !.#._i=1 !.#._n=size

                 do i=1 for size;  y=@.i; a=abs(y)
                 @.i=right(a,width,0)
                 if y<0 then @.i='-'@.i
                 end
 do while #\==0;    ctr.=0;    L='ffff'x;    H=""
 low=!.#._b;   n=!.#._n;   radi=!.#._i;   #=#-1
     do j=low for n;   parse var @.j =(radi) _ +1;   ctr._=ctr._+1
     if ctr._==1 then if _\== then do
                                     if _<<L then L=_;   if _>>H then H=_
                                     end
     end   /*j*/
 if L>>H then iterate
 _=""
 if L==H then if ctr._==0 then do;  #=#+1
                                            !.#._b=low
                                            !.#._n=n
                                            !.#._i=radi+1;    iterate
                               end
 L=c2d(L);  H=c2d(H);  ?=ctr._+low;  top._=?;  ts=mote;  max=L;  lc=""
              do k=L to H;   _=d2c(k,1);   cen=ctr._
              if cen>ts then parse value  cen  k   with   ts  max
              ?=?+cen;   top._=?
              end   /*k*/
 pivot=low
    do while pivot<low+n;  it=@.pivot
         do forever
         parse var it =(radi) _ +1; cen=top._-1; if pivot>=cen then leave
         top._=cen;  ?=@.cen;  @.cen=it;  it=?
         end    /*forever*/
    top._=pivot;  @.pivot=it;  pivot=pivot+ctr._
    end         /*while pivot<low+n*/
 i=max
   do until i==max;     _=d2c(i,1);   i=i+1;   if i>H then i=L;   d=ctr._
   if d<=mote then do; if d>1 then call .radSortP top._,d;  iterate; end
   #=#+1;     !.#._b=top._
              !.#._n=d
              !.#._i=radi+1
   end   /*until i==max*/
 end     /*while #\==0 */
       do i=1 for size;   @.i=@.i+0;   end   /*i*/

return /*───────────────────────────────────.radSortP subroutine───────────────*/ .radSortP: parse arg bbb,nnn

         do k=bbb+1 for nnn-1;   q=@.k
             do j=k-1 by -1 to bbb while q<<@.j;  jp=j+1;  @.jp=@.j;  end
         jp=j+1;   @.jp=q
         end  /*k*/

return</lang> output (with the middle section elided.)

item   1 after the radix sort:  -42
item   2 after the radix sort:    0
item   3 after the radix sort:    2
item   4 after the radix sort:    3
item   5 after the radix sort:    4
item   6 after the radix sort:    5
item   7 after the radix sort:    5
item   8 after the radix sort:    6
item   9 after the radix sort:    6
item  10 after the radix sort:    7
item  11 after the radix sort:    7
item  12 after the radix sort:    7
item  13 after the radix sort:    8
  .
  .
  .
(middle section elided.)
  .
  .
  .
item  92 after the radix sort:   40
item  93 after the radix sort:   41
item  94 after the radix sort:   43
item  95 after the radix sort:   43
item  96 after the radix sort:   45
item  97 after the radix sort:   47
item  98 after the radix sort:   49
item  99 after the radix sort:   53
item 100 after the radix sort:   55
item 101 after the radix sort:   59
item 102 after the radix sort:   61
item 103 after the radix sort:   67
item 104 after the radix sort:   71
item 105 after the radix sort:   73
item 106 after the radix sort:   79
item 107 after the radix sort:   83
item 108 after the radix sort:   89
item 109 after the radix sort:   97
item 110 after the radix sort:  101
item 111 after the radix sort:  103
item 112 after the radix sort:  107
item 113 after the radix sort:  109
item 114 after the radix sort:  113

Ruby

Negative number handling courtesy the Tcl solution. <lang ruby>class Array

 def radix_sort(base=10)
   ary = dup
   rounds = (Math.log(self.max.abs)/Math.log(base)).ceil
   rounds.times do |i|
     buckets = Hash.new {|h,k| h[k] = []}
     ary.each do |n|
       digit = (n/base**i) % base
       digit = digit + base unless n<0
       buckets[digit] << n
     end
     ary = buckets.values_at(*(0..2*base)).compact.flatten
     p [i, ary] if $DEBUG
   end
   ary
 end
 def radix_sort!(base=10)
   replace radix_sort(base)
 end

end

p [1, 3, 8, 9, 0, 0, 8, 7, 1, 6].radix_sort p [170, 45, 75, 90, 2, 24, 802, 66].radix_sort p [170, 45, 75, 90, 2, 24, -802, -66].radix_sort</lang>

running with $DEBUG on produces:

[0, [0, 0, 1, 1, 3, 6, 7, 8, 8, 9]]
[0, 0, 1, 1, 3, 6, 7, 8, 8, 9]
[0, [170, 90, 2, 802, 24, 45, 75, 66]]
[1, [2, 802, 24, 45, 66, 170, 75, 90]]
[2, [2, 24, 45, 66, 75, 90, 170, 802]]
[2, 24, 45, 66, 75, 90, 170, 802]
[0, [-66, -802, 170, 90, 2, 24, 45, 75]]
[1, [-66, -802, 2, 24, 45, 170, 75, 90]]
[2, [-802, -66, 2, 24, 45, 75, 90, 170]]
[-802, -66, 2, 24, 45, 75, 90, 170]

Tcl

Translation of: Python

<lang tcl>package require Tcl 8.5 proc splitByRadix {lst base power} {

   # create a list of empty lists to hold the split by digit
   set out [lrepeat [expr {$base*2}] {}]
   foreach item $lst {

# pulls the selected digit set digit [expr {($item / $base ** $power) % $base + $base * ($item >= 0)}] # append the number to the list selected by the digit lset out $digit [list {*}[lindex $out $digit] $item]

   }
   return $out

}

  1. largest abs value element of a list

proc tcl::mathfunc::maxabs {lst} {

   set max [abs [lindex $lst 0]]
   for {set i 1} {$i < [llength $lst]} {incr i} {

set v [abs [lindex $lst $i]] if {$max < $v} {set max $v}

   }
   return $max

}

proc radixSort {lst {base 10}} {

   # there are as many passes as there are digits in the longest number
   set passes [expr {int(log(maxabs($lst))/log($base) + 1)}]
   # For each pass...
   for {set pass 0} {$pass < $passes} {incr pass} {

# Split by radix, then merge back into the list set lst [concat {*}[splitByRadix $lst $base $pass]]

   }
   return $lst

}</lang> Demonstrations: <lang tcl>puts [radixSort {1 3 8 9 0 0 8 7 1 6}] puts [radixSort {170 45 75 90 2 24 802 66}] puts [radixSort {170 45 75 90 2 24 -802 -66}]</lang> Output:

0 0 1 1 3 6 7 8 8 9
2 24 45 66 75 90 170 802
-802 -66 2 24 45 75 90 170