(Disclaimer: as you mentioned in the question that this is a homework assignment, I strongly suggest you to first have a go solving the problem yourself, before "peeking" into the following solution (although there are many ways to do this). A good way to learn solving a complex problem is to first break it down into smaller "chunks", come up with some very simple inputs and expected outputs, followed by implementing your own codes. Use Google searches to find tips / hints. I'm putting my own solution here purely for the benefit of sparking inspirations. There may be more elegant / efficient way to do this.)
Step 1: Break this problem into two smaller parts
For ease of understanding I'd break this down into two steps:
Step 2: Visualise sample inputs and expected outputs
Before even attempting implementing codes, I always find it beneficial to "visualise" some very simple example inputs and expected outputs. Let's visualise some scenarios.
Scenario 1 - Input is an already flatten list
- input:
[1, 2, 3, 4, 5, 6]
- part 1 (deep flattening) output:
[1, 2, 3, 4, 5, 6]
- part 2 (max element in list) output:
6
Scenario 2 - Input is an already flatten tuple
- input:
(1, 2, 3, 4, 5, 6)
- part 1 (deep flattening) output:
[1, 2, 3, 4, 5, 6]
- part 2 (max element in list) output:
6
Scenario 3 - Input is a deeply nested list
- input:
[1, [2, [3, 4, 5, 6]]]
- part 1 (deep flattening) output:
[1, 2, 3, 4, 5, 6]
- part 2 (max element in list) output:
6
Scenario 4 - Input is a deeply nested tuple
- input:
(1, (2, (3, 4, 5, 6)))
- part 1 (deep flattening) output:
[1, 2, 3, 4, 5, 6]
- part 2 (max element in list) output:
6
Scenario 5 - Input is a deeply nested list/tuple combined. eg 1
- input:
[1, (2, [3, 4, 5, 6])]
- part 1 (deep flattening) output:
[1, 2, 3, 4, 5, 6]
- part 2 (max element in list) output:
6
Scenario 6 - Input is a deeply nested list/tuple combined. eg 2
- input:
(1, [2, (3, 4, 5, 6)])
- part 1 (deep flattening) output:
[1, 2, 3, 4, 5, 6]
- part 2 (max element in list) output:
6
Scenario 7 - Input is an integer
- input:
6
- part 1 (deep flattening) output:
[6]
- part 2 (max element in list) output:
6
Scenario 8 - (optional) Input is an empty list
- input:
[]
- part 1 (deep flattening) output:
[]
- part 2 (max element in list) output:
None
Scenario 9 - (optional) Input is an empty tuple
- input:
()
- part 1 (deep flattening) output:
[]
- part 2 (max element in list) output:
None
Step 3 - implement Part 1 (deep flattening)
This is my code (works for some test case scenarios above. Tweak as needed to make it more robust).
def deep_flatten(t):
# if t is an int, just return a list with that int in it. No recursions needed.
if isinstance(t, int):
return [t]
# if t is a list or tuple, do some recursions to deep-flatten it:
elif isinstance(t, (list, tuple)):
# initialise result
result = []
# define a recursive function
def update_result(t):
for item in t:
if isinstance(item,(list, tuple)):
update_result(item)
else:
result.append(item)
# mutate result by performing recursions
update_result(t)
# return it
return result
Step 4 - implement Part 2 (max element of a list)
This is the ultimate code in question, using the deep_flatten
helper function.
def max_val(t):
""" t, tuple or list
Each element of t is either an int, a tuple, or a list
No tuple or list is empty
Returns the maximum int in t or (recursively) in an element of t """
# use our helper deep flattening function to output a flatten list
t_flatten = deep_flatten(t)
# empty tuple / list case
if len(t_flatten) == 0:
return None
# return the max element in a non-empty list / tuple input
return max(t_flatten)
Step 5 - do some testing
Do some testings against the scenarios. print out the variables to check result is as expected.
Scenario 1
t1 = [1, 2, 3, 4, 5, 6]
t1_flatten = deep_flatten(t1) # -> [1, 2, 3, 4, 5, 6]
t1_max = max_val(t1) # -> 6
Scenario 2
t2 = (1, 2, 3, 4, 5, 6)
t2_flatten = deep_flatten(t2) # -> [1, 2, 3, 4, 5, 6]
t2_max = max_val(t2) # -> 6
Scenario 3
t3 = [1, [2, [3, 4, 5, 6]]]
t3_flatten = deep_flatten(t3) # -> [1, 2, 3, 4, 5, 6]
t3_max = max_val(t3) # -> 6
Scenario 4
t4 = (1, (2, (3, 4, 5, 6)))
t4_flatten = deep_flatten(t4) # -> [1, 2, 3, 4, 5, 6]
t4_max = max_val(t4) # -> 6
Scenario 5
t5 = [1, (2, [3, 4, 5, 6])]
t5_flatten = deep_flatten(t5) # -> [1, 2, 3, 4, 5, 6]
t5_max = max_val(t5) # -> 6
Scenario 6
t6 = (1, [2, (3, 4, 5, 6)])
t6_flatten = deep_flatten(t6) # -> [1, 2, 3, 4, 5, 6]
t6_max = max_val(t6) # -> 6
Scenario 7
t7 = 6
t7_flatten = deep_flatten(t7) # -> [6]
t7_max = max_val(t7) # -> 6
Scenario 8
t8 = []
t8_flatten = deep_flatten(t8) # -> []
t8_max = max_val(t8) # -> None
Scenario 9
t9 = ()
t9_flatten = deep_flatten(t9) # -> []
t9_max = max_val(t9) # -> None
Sample case as per the question:
print( max_val((5, (1,2), [[1],[2]])) ) # -> 5
print( max_val((5, (1,2), [[1],[9]])) ) # -> 9