In [77]:
    
def counting_sort(a):
    return _counting_sort(a, max(a))
def _counting_sort(a, max_value):
    
    result = []
    counter = [0] * (max_value + 1)
    
    for i in a:
        counter[i] += 1
    
    for i, count in enumerate(counter):
        result.extend([i] * count)
    
    return result
    
In [76]:
    
d = [4,2,1,10,10,5,3,22, 7, 1]
print(counting_sort(d))
    
    
In [5]:
    
def counting_sort_in_place(a):
    """
    in-place counting sort
    http://p-nand-q.com/python/algorithms/sorting/countingsort.html
    """
    
    counter = [0] * (max(a) + 1)
    for i in a:
        counter[i] += 1
    
    pos = 0
    for i, count in enumerate(counter):
        for _ in range(count):
            a[pos] = i
            pos += 1
    return a
    
In [6]:
    
d = [4,2,1,10,10,5,3,22, 7, 1]
print(counting_sort_in_place(d))
    
    
In [32]:
    
def counting_sort_alpha(a):
    max_value = 255
    
    result = []
    counter = [0] * (max_value + 1)
    
    for i in a:
        counter[ord(i)] += 1
    
    for i, count in enumerate(counter):
        result.extend([i] * count)
    
    return "".join(chr(n) for n in result)
    
In [33]:
    
d = "thisisasimplesort"
print(counting_sort_alpha(d))
    
    
In [35]:
    
import unittest
 
class Test( unittest.TestCase ):
 
    def testCountingSortInPlace( self ):
        A = [6, 4, 3, 2, 1, 4, 3, 6, 6, 2, 4, 3, 4]
        k = 6
        counting_sort_in_place( A)
        for i in range( 1, len( A ) ):
            if A[i - 1] > A[i]:
                self.fail( "counting_sort_in_place method fails." )
    def testCountingSort( self ):
        A = [6, 4, 3, 2, 1, 4, 3, 6, 6, 2, 4, 3, 4]
        k = 6
        A = counting_sort(A)
        for i in range( 1, len( A ) ):
            if A[i - 1] > A[i]:
                self.fail( "counting_sort method fails." )
    
    def testCountingSortAlpha(self):
        A = "thisisasimplesort"
        A = counting_sort_alpha(A)
        for i in range( 1, len( A ) ):
            if ord(A[i - 1]) > ord(A[i]):
                self.fail( "counting_sort_alpha method fails." )
    
In [36]:
    
unittest.main(argv=['first-arg-is-ignored'], exit=False)
    
    
    Out[36]:
Radix-sort sorts $ \mathtt{w}$-bit integers by using $ \mathtt{w}/\mathtt{d}$ passes of counting-sort to sort these integers $ \mathtt{d}$ bits at a time.
More precisely, radix sort first sorts the integers by their least significant $ \mathtt{d}$ bits, then their next significant $ \mathtt{d}$ bits, and so on until, in the last pass, the integers are sorted by their most significant $ \mathtt{d}$ bits.
In [38]:
    
A = [16, 4, 3, 2, 1, 4, 3, 6, 6, 2, 4, 3, 4]
import math
math.floor(math.log10(max(A))) + 1
    
    Out[38]:
In [53]:
    
def get_num_difit(n):
    i = 0
    while n > 0:
        n //= 10
        i += 1
    return i
    
In [55]:
    
get_num_difit(1030)
    
    Out[55]:
In [70]:
    
# source: https://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Radix_sort
import math
def radix_sort(a):
    # num_digit = math.floor(math.log10(max(a))) + 1
    num_digit = get_num_difit(max(a))
    return _radix_sort(a, num_digit)
def _radix_sort(a, num_digit):
    radix = 10
    
    for x in range(num_digit):
        bins = [[] for i in range(radix)]
        
        for y in a:
            bins[(y//radix**x)%radix].append(y)
            
        a = []
        for section in bins:
            a.extend(section)
    return a
    
In [93]:
    
# source https://www.lewuathe.com/radix-sort-in-python.html
# TODO
def get_digit(n, d):
    for i in range(d-1):
        n //= 10
    return n % 10
def get_num_difit(n):
    i = 0
    while n > 0:
        n //= 10
        i += 1
    return i
def counting_sort(a, max_value, get_index):
    counter = [0] * (max_value + 1)
    
    result = []
    for i in a:
        counter[get_index(i)] += 1
    print(counter)  
    for i, count in enumerate(counter):
            result.extend([get_index(i)] * count) 
    
    return result
def radix_sort(a):
    return _radix_sort(a, max(a))
def _radix_sort(a, max_value):
    num_digits = get_num_difit(max_value)
    
    for d in range(num_digits):
    # Counting sort takes O(n+k)
        arr = counting_sort(a, 10, lambda a: get_digit(a, d+1))
    return arr
    
In [94]:
    
A = [16, 4, 3, 42, 134, 344, 3554, 6, 26, 2, 24, 34, 124]
print(radix_sort(A))
    
    
In [68]:
    
import unittest
 
class Test( unittest.TestCase ):
 
    def testRadixSort( self ):
        A = [16, 4, 3, 42, 134, 344, 3554, 6, 26, 2, 24, 34, 124]
        
        A = radix_sort(A)
        print(A)
        for i in range( 1, len( A ) ):
            if A[i - 1] > A[i]:
                self.fail( "radix_sort method fails." )
    
In [69]:
    
unittest.main(argv=['first-arg-is-ignored'], exit=False)
    
    
    
    
    Out[69]:
In [ ]: