import random
import time

# ---------------------------------------------------------------------------------------
#      R A N D O M   S T R I N G S   G E N E R A T O R
# ---------------------------------------------------------------------------------------

random.seed( 2300543 )
random.seed( 5300543 )
# A simplified Markov chain model for word generation
ch = ["", "aeiouy", "bdhklmnpr", "cfgqsvwz", ""]   # start, vowel, easy consonant, hard consonant, end
P = [[ 0.0, 0.15, 0.95, 1.00, 1.00 ],\
     [ 0.0, 0.10, 0.77, 0.80, 1.00],\
     [ 0.0, 0.50, 0.77, 0.80, 1.00],\
     [ 0.0, 0.40, 0.80, 0.80, 1.00] ]

def rndword():
    state = 0
    rnd = random.uniform(0,1)
    while rnd > P[0][state]: state += 1
    w = ""
    while True:
        w += ch[state][random.randint(0, len(ch[state])-1 )]
        rnd = random.uniform(0,1)
        next = 0
        while rnd > P[state][next]: next += 1
        if next == 4: break
        state = next
    return w


def randStrings( N ):
    return [rndword() for _foo in range(N)]

# ---------------------------------------------------------------------------------------
#      S O R T   C O M P A R A T O R S
# ---------------------------------------------------------------------------------------

def byLength( str ):
    return len(str)

def byLengthAnd2nd( str ):
    if len(str) < 2:
        return len(str), -1
    else:
        return len(str), str[1]

def byLast( str ):
    return str[-1]

def byLengthAnd2ndAndAll( str1, str2 ):
    if len(str1) == len(str2) == 1:
        return 0 # we do not care, just for demonstration purposes

    if len(str1) < len(str2): return -1
    if len(str1) > len(str2): return 1
    # equal length remains, check second char
    if str1[1] < str2[1]: return -1
    if str1[1] > str2[1]: return 1
    # if all previous criteria are the same comepare strings themselves
    if str1 < str2: return -1
    if str1 > str2: return 1
    return 0 #  equal strings


import functools
# In Python 3.x, the comparator has to be turned FORMALLY(!) into a key
# like in the example:
#    myComparator = functools.cmp_to_key(myKeyFunction)
#    myList.sort(key=myComparator)

comparator_bLA2AA = functools.cmp_to_key( byLengthAnd2ndAndAll )

# ---------------------------------------------------------------------------------------
#      E X A M P L E S
# ---------------------------------------------------------------------------------------

words = randStrings(20) + ["abd", "abc"]
words = randStrings(8) + ["abd", "abc"]
print( "----- unsorted -----" )
print( "\n".join(words) )
print( "----- just sorted -----" )
print( "\n".join( sorted(words) ) )
print( "----- sorted by len directly -----" )
print( "\n".join( sorted( words, key=len) ) )
print( "----- sorted by function bylength -----" )
print( "\n".join( sorted( words, key=byLength) ) )
print( "----- sorted by last character  -----" )
print(  "\n".join( sorted( words, key=byLast) ) )
print( "----- sorted by function byLengthAnd2nd  -----" )
print(  "\n".join( sorted( words, key=byLengthAnd2nd) ) )
print( "----- sorted by comparator_bLA2AA  -----" )
print(  "\n".join( sorted( words, key=comparator_bLA2AA) ) )

#
arr = [(2, 3, 4), (1, 3, 9), (6, 4, 4), (10, 5, 2)]

print( sorted(arr, key=max) )
print( sorted(arr, key=min) )
print( sorted(arr, key=sum) )


arr = [(6, 3, 4), (3, 3, 4), (1, 3, 9),  (10, 3, 2), (4, 5, 6)]
# More examples
# https://docs.python.org/2/howto/sorting.html
from operator import itemgetter
print( sorted(arr, key=itemgetter(1,2,0)) )




