Not the exercise. This finds the largest number anywhere in a list of lists, and the only difference from adding them up is how the answers are combined.
def biggest(items):
best = float("-inf")
for element in items:
if isinstance(element, list):
best = max(best, biggest(element))
else:
best = max(best, element)
return best
print(biggest([3, [9, [1]], 4])) # -> 9
- max keeps only the winner
Each inner call reports its own largest value, and the caller keeps whichever is bigger. Adding them would answer a different question.
- A starting value that cannot win by accident
-inf is smaller than anything, so the first real value always replaces it. Starting at 0 would be wrong for a list of negative numbers.
- The same skeleton as a sum
Loop, recurse into lists, combine. Most recursive functions over nested data are this loop with a different combining step.
The list you are given is one level. Its depth is 1 plus the depth of its deepest inner list, and depth can measure an inner list for you.
Keep track of the deepest inner answer, starting at 0 for "no inner lists yet". For each element that is a list, compare depth(element) with it.
deepest = 0; for each list element, deepest = max(deepest, depth(element)); return 1 + deepest. A list with no lists inside returns 1 + 0.
def depth(items): deepest = ____ for element in items: if isinstance(element, list): deepest = ____(deepest, depth(element)) return ____ + deepest
def depth(items):
deepest = 0
for element in items:
if isinstance(element, list):
deepest = max(deepest, depth(element))
return 1 + deepest
Every call adds one for the list it was given. Summed down the deepest chain of calls, those ones are the answer.
deepest starts at 0, so a flat or empty list returns 1 + 0. The empty list needs no special case, because it is a list like any other.
max of an empty sequence raises ValueError, and a flat list has no inner lists to feed it. max(..., default=0) fixes that, and is a fine one-line version once you know why the default is needed.
To check whether data is too deep for recursion to handle, measuring it with recursion is the wrong tool: it hits the same limit it is checking for. An explicit stack of (list, level) pairs measures any depth.
- Return the path to the deepest point as a list of positions, so [[1], [[2]]] gives [1, 0, 0].
- Measure depth with a loop and a stack of (list, level) pairs, with no recursion.
- Count how many values sit at each depth, returning a dict of depth to count.