
def rec_seq_downup( N ):
    if N < 0:
        return
    print( N, end = ' ' )
    rec_seq_downup( N-1 )
    print( N, end = ' ' )

def rec_binary_in( N ):
    if N < 0:
        return
    rec_binary_in( N-1 )
    print( N, end = ' ' )
    rec_binary_in( N-1 )

def rec_binary_pre( N ):
    if N < 0:
        return
    print( N, end = ' ' )
    rec_binary_pre( N-1 )
    rec_binary_pre( N-1 )

def rec_binary_post( N ):
    if N < 0:
        return
    rec_binary_post( N-1 )
    rec_binary_post( N-1 )
    print( N, end = ' ' )

def rec_binary_tree( N, depth ):
    if N < 0:
        return
    rec_binary_tree( N-1, depth+1 )
    print( " "*3*depth,  N )
    rec_binary_tree( N-1, depth+1 )

def rec_binary_tree2( N, depth ):
    if N < 0:
        return
    rec_binary_tree2( N-2, depth+1 )
    print( " "*3*depth,  N )
    rec_binary_tree2( N-1, depth+1 )

def rec_ternary_pre( N ):
    if N < 0:
        return
    print( N, end = ' ' )
    rec_ternary_pre( N-1 )
    rec_ternary_pre( N-1 )
    rec_ternary_pre( N-1 )

def rec_hello( K ):
    if( K == 0 ):
        return
    rec_hello( K-1 )
    rec_hello( K-1 )
    print("Hello!")

def rec_hello_count( K ):
    if( K == 0 ):
        return 0
    calls1  = rec_hello_count( K-1 )
    calls2 = rec_hello_count( K-1 )
    print("Hello!")
    return calls1 + calls2 + 1

'''
All substrings of "abcd"
A substring, in this case, is not necessarily a contiguous one

 "abcd" == "a" + "bcd"
       1. all substrings of "bcd":
            ["", "b", "c", "d",  "bc", "cd", "bcd"]
       2. prepend "a" to all substrings of "bcd":
            ["a", "ab", "ac", "ad",  "abc", "acd", "abcd"]
       3. join 1. and 2.
'''
def rec_allSubStrings(aString):

    if len( aString ) == 1:
        return  [ "", aString[0:1] ]

    withoutFirst = rec_allSubStrings(aString[1:])
    withFirst = [ aString[0] + elem for elem in withoutFirst ]

    all = withoutFirst + withFirst

    return all


def rec_allSums( values ):

    if len( values ) == 1:
        return  [ 0 , values[0] ]

    withoutFirst = rec_allSums( values[1:] )
    withFirst = [ values[0] + elem for elem in withoutFirst ]

    all = withoutFirst + withFirst

    return all


def rec_allSubsets(aSet):
    if len(aSet) == 0:
        return  [ [] ]
    withoutFirst = rec_allSubsets(aSet[1:])
    withFirst = [ ( [aSet[0]] + subset) for subset in withoutFirst]
    all = withoutFirst + withFirst
    return all


rec_seq_downup( 4 )
print()

rec_binary_pre( 4 )
print()

rec_binary_in( 4 )
print()

rec_binary_post( 4 )
print()


rec_binary_tree( 4, 0 )
print()

rec_binary_tree2( 5, 0 )

rec_ternary_pre( 4 )
print()

rec_ternary_pre( 10 )
print()

rec_hello( 4 )
print()

N = rec_hello_count( 2 )
print( N )

N = rec_hello_count( 3 )
print( N )

N = rec_hello_count( 4 )
print( N )

all = rec_allSubStrings("12345")
print( all )
print()

vals = [1, 2,  5, 10, 20, 50]
allsums =  rec_allSums( vals )
print( allsums )
print()

vals = [1, 2,  5, 10, 20, 50]
allsets = rec_allSubsets( vals )
print( allsets )
print()

all2 = [ (sum(set), set) for set in allsets]
print( all2 )
print()

all2.sort(key=lambda tup: tup[0])
for item in all2:
    print( item )
print()



