# some sorts
import sys
#sys.setrecursionlimit(1000000)

def select(L):
    """Produce copy of L in sorted order

    >>> select([3, 1, 2])
    [1, 2, 3]
    """
    L1 = L[:]
    for i in range(len(L1)):
        m = min(L1[i:])
        j = L1.index(m,i)
        L1[i], L1[j] = L1[j], L1[i]
    return L1


def quick(L):
    if len(L) > 1 :
        return (quick([x for x in L[1:] if x < L[0]])
                + [L[0]] + quick([x for x in L[1:] if x >= L[0]]))
    else :
        return L

def merge(L1, L2):
    """return merge of L1 and L2

    >>> merge([1, 3, 5], [2, 4, 6])
    [1, 2, 3, 4, 5, 6]
    >>> merge([1, 2, 3], [0, 4, 5])
    [0, 1, 2, 3, 4, 5]
    >>> merge([0], [1, 2, 3, 4])
    [0, 1, 2, 3, 4]
    """
    L = []
    L1.reverse()
    L2.reverse()
    while L1 and L2:
        if L1[-1] < L2[-1]:
            L.append(L1.pop(-1))
        else:
            L.append(L2.pop(-1))
    L1.reverse()
    L2.reverse()
    return L + L1 + L2

def merge_sort(L):
    """Produce copy of L in non-decreasing order

    >>> merge_sort([1, 5, 3, 4, 2])
    [1, 2, 3, 4, 5]
    """
    if len(L) < 2 :
        return L[:]
    else :
        return merge(merge_sort(L[:len(L)//2]), merge_sort(L[len(L)//2:]))

def count_sort(L):
    """silly functional sort.  See radix sort for something serious"""
    count_list = [0, ] * len(L)
    for i in L:
        count_list[i] += 1

    L1 = [] # blank slate!
    for i in range(len(count_list)):
        for j in range(count_list[i]):
            L1.append(i)
    return L1


if __name__== '__main__':
    import doctest
    doctest.testmod()
    from time import time, clock
    from random import shuffle
    L = list(range(1000000))
    shuffle(L)
   #start = time()
   #select(L)
   #print("select sort: {} for {} items".format(time() - start, len(L)))
   #start = time()
   #quick(L)
   #print("quick sort: {} for {} items".format(time() - start, len(L)))
   #start = time()
   #merge_sort(L)
   #print("merge sort: {} for {} items".format(time() - start, len(L)))
    start = time()
    count_sort(L)
    print("count sort: {} for {} items".format(time() - start, len(L)))
    L2 = L[:] # let built-in sort in place...
    start = time()
    L2.sort()
    print("built-in sort: {} for {} items".format(time() - start, len(L)))
