"""
some recursive functions on nested lists
"""


def depth(obj):
    """
    Return 0 if obj is a non-list, or 1 + maximum
    depth of elements of obj, a possibly nested
    list of objects.

    Assume obj has finite nesting depth

    @param list[object]|object obj: possibly nested list of objects
    @rtype: int

    >>> depth(3)
    0
    >>> depth([])
    1
    >>> depth([[], [[]]])
    3
    >>> depth([1, 2, 3])
    1
    >>> depth([1, [2, 3], 4])
    2
    """
    if obj == []:
        return 1
    elif isinstance(obj, list):
        return 1 + max([depth(x) for x in obj])
    else:
        return 0


def rec_max(obj):
    """
    Return obj if it's an int, or the maximum int in obj,
    a possibly nested list of numbers.

    Assume: obj is an int or non-empty list with finite nesting depth,
    and obj doesn't contain any empty lists

    @param int|list[int|list[...]] obj: possibly nested list of int
    @rtype: int

    >>> rec_max([17, 21, 0])
    21
    >>> rec_max([17, [21, 24], 0])
    24
    >>> rec_max(31)
    31
    """
    if isinstance(obj, list):
        return max([rec_max(x) for x in obj])
    else:
        return obj


def concat_strings(string_list):
    """
    Concatenate all the strings in possibly-nested string_list.

    @param list[str]|str string_list:
    @rtype: str

    >>> concat_strings("brown")
    'brown'
    >>> concat_strings(["now", "brown"])
    'nowbrown'
    >>> concat_strings(["how", ["now", "brown"], "cow"])
    'hownowbrowncow'
    """


def nested_contains(list_, value):
    """
    Return whether list_, or any nested sub-list of list_ contains value.

    @param list list_: list to search
    @param object value: non-list value to search for
    @rtype: bool

    >>> list_ = ["how", ["now", "brown"], 1]
    >>> nested_contains(list_, "brown")
    True
    >>> nested_contains([], 5)
    False
    >>> nested_contains([5], 5)
    True
    """
    # check out Python built-in any
    if all([not isinstance(x, list) for x in list_]):
        return value in list_
    else:
        return any([nested_contains(x, value)
                if isinstance(x, list) else (x == value)
                for x in list_])


def nested_count(list_):
    """
    Return the number of non-list elements of list_ or its nested sub-lists.

    @param list list_: possibly nested list to count elements of
    @rtype: int

    >>> list_ = ["how", ["now", "brown"], "cow"]
    >>> nested_count(list_)
    4
    """
    # functional if helps here
    pass


if __name__ == '__main__':
    import doctest
    doctest.testmod()
