# given a list, return a "flattened" list containing the same elements
# I.e. [ [[1, 2], 3] , 4, 5, [[[[6]]]], [], 'z' ] --> [1,2,3,4,5,6,'z']
#
# Basically, non-lists are left alone, while any sublists are first themselves flattened and
# then their elements are made part of the result
# E. g. flatten( [ [ 1, 2] , 3 ] ) ->  elements of [1, 2] made part of result along with 3, so [1, 2, 3]
#

def flatten1(aList):
    result = []
    for item in aList:
        if type(item) == list:
            for subListItem in item:
                result.append(subListItem)
        else:
            result.append(item)
    return result

def flatten(aList):
    result = []
    for item in aList:
        if type(item) == list:
            result = result + flatten(item)
            #result.extend(flatten(item))
        else:
            result.append(item)
    return result

#
# Write a recursive function, printPattern(s), that takes a string
# as input and return a new string as implied by the examples below.
#
# 'a' -> 'a'
# 'ab' -> 'aabaa'
# 'bca' -> 'bbbccaccbbb'
# 'zaxy' -> 'zzzzaaaxxyxxaaazzzz'
#
def pattern(s):
    if len(s) == 1:
        return s
    else:
        return len(s)*s[0] + pattern(s[1:]) + len(s)*s[0]


# See definition of nesting depth in lec15 presentation slides
#
def nestingDepth(inList):
    maxSubNestingDepth = None
    for item in inList:
        if type(item) == list:
            subNestingDepth = nestingDepth(item)
            if (maxSubNestingDepth == None) or (subNestingDepth > maxSubNestingDepth):
                maxSubNestingDepth = subNestingDepth
    if maxSubNestingDepth != None:
        return maxSubNestingDepth + 1
    else:
        return 0
    
# same as above but all recursion - no loops
def nestingDepth2(inList):
    nestingLevels = 0
    maxSubNestingDepth = None
    if type(inList) != list:
        return None
    elif len(inList) == 0:
        return 0
    else:
        restNestingDepth = nestingDepth2(inList[1:])
        item0nestingDepth = nestingDepth2(inList[0])
        if item0nestingDepth == None:
            return restNestingDepth
        else:
            return max(restNestingDepth, item0nestingDepth + 1)


def testND(nd=nestingDepth):
    res1 = nd([])
    print("For: []result produced: {}.  {}".format(res1, "CORRECT" if (res1==0) else "INCORRECT"))
    res1 = nd([3])
    print("For: [3] result produced: {}.  {}".format(res1, "CORRECT" if (res1==0) else "INCORRECT"))
    res1 = nd([[],[]])
    print("For: [[],[]] result produced: {}.  {}".format(res1, "CORRECT" if (res1==1) else "INCORRECT"))
    res1 = nd([3, 2.0, 'string'])
    print("For: [3, 2.0, 'string'] result produced: {}.  {}".format(res1, "CORRECT" if (res1==0) else "INCORRECT"))
    res1 = nd([5, [2]])
    print("For: [5, [2]] result produced: {}.  {}".format(res1, "CORRECT" if (res1==1) else "INCORRECT"))
    res1 = nd([5, [2, 3, [3, 2]]])
    print("For: [5, [2, 3, [3, 2]]] result produced: {}.  {}".format(res1, "CORRECT" if (res1==2) else "INCORRECT"))
    res1 = nd([[[[[[]]]]]])
    print("For: [[[[[[]]]]]] result produced: {}.  {}".format(res1, "CORRECT" if (res1==5) else "INCORRECT"))
    res1 = nd([[[[[[]]]]], 1, [[[[[[2]]]]]]])
    print("For: [[[[[[]]]]], 1, [[[[[[2]]]]]]] result produced: {}.  {}".format(res1, "CORRECT" if (res1==6) else "INCORRECT"))
    res1 = nd([[[[],[2,[[3,[[]],[[4, [[]]]]]]]]]])
    print("For: [[[[],[2,[[3,[[]],[[4, [[]]]]]]]]]] result produced: {}.  {}".format(res1, "CORRECT" if (res1==9) else "INCORRECT"))
       

    
