Chapter 4 Exercises
Comprehensive exercises covering functions in Python, sorted from easiest to hardest.
Exercises
Exercise 1: Range Sum Function
Write a function called range_sum that takes in a range of numbers: start (inclusive), end (exclusive), and an optional step (default 1). It should return the sum of all the numbers in the range.
Range Sum Function
def range_sum(start, end, step=1): total = 0 for i in range(start, end, step): total += i return total
start = int(input())end = int(input())step_input = input().strip()step = int(step_input) if step_input else 1
result = range_sum(start, end, step)print(result)Exercise 2: Sort Strings by Length
Write a function called sort_by_length that takes a list of strings and returns a list of strings sorted by their length (shortest first).
Sort Strings by Length
def sort_by_length(strings): return sorted(strings, key=len)
n = int(input())strings = []for i in range(n): strings.append(input())
result = sort_by_length(strings)print(result)Exercise 3: Check Unique Elements
Write a function called all_unique that takes in a list and returns True if all the elements are unique, otherwise returns False.
Check Unique Elements
def all_unique(lst): return len(lst) == len(set(lst))
n = int(input())numbers = []for i in range(n): numbers.append(int(input()))
result = all_unique(numbers)print(result)Exercise 4: Parse Numbers from Line
Write a function called parse_numbers that takes a string containing space-separated numbers and returns a list of integers. Read a line of space-separated numbers from input, call the function, and print the resulting list.
Parse Numbers from Line
def parse_numbers(line): return [int(num) for num in line.split()]
line = input()numbers = parse_numbers(line)print(numbers)Exercise 5: Character to ASCII Dictionary
Write a function called char_to_ascii that creates and returns a dictionary containing the characters from A to Z in uppercase as keys, and their decimal ASCII representation as values. Print the dictionary.
Character to ASCII Dictionary
def char_to_ascii(): result = {} for i in range(26): char = chr(ord('A') + i) result[char] = ord(char) return result
dictionary = char_to_ascii()print(dictionary)Exercise 6: Fibonacci Number
Write a function called fibonacci that takes an integer n and returns the nth Fibonacci number. The Fibonacci sequence starts with 0, 1, 1, 2, 3, 5, 8, … (where fib(0)=0, fib(1)=1, fib(2)=1).
Fibonacci Number
def fibonacci(n): if n == 0 or n == 1: return 0 a, b = 0, 1 for i in range(2, n + 1): a, b = b, a + b return b
n = int(input())result = fibonacci(n)print(result)Exercise 7: Even Fibonacci Numbers
Write a function called even_fibonacci that takes an integer m and returns a list of all even Fibonacci numbers that are less than m. Use the fibonacci function from the previous exercise or implement it inline.
Even Fibonacci Numbers
def fibonacci(n): if n == 0 or n == 1: return n a, b = 0, 1 for i in range(2, n + 1): a, b = b, a + b return b
def even_fibonacci(m): result = [] i = 0 while True: fib = fibonacci(i) if fib >= m: break if fib % 2 == 0: result.append(fib) i += 1 return result
m = int(input())result = even_fibonacci(m)print(result)Exercise 8: Create Matrix
Write a function called create_matrix that takes the number of rows and columns, and creates a matrix (list of lists) where each entry (0-indexed). Return and print the matrix.
Create Matrix
def create_matrix(rows, cols): matrix = [] for i in range(rows): row = [] for j in range(cols): row.append(i + j) matrix.append(row) return matrix
rows = int(input())cols = int(input())result = create_matrix(rows, cols)print(result)Exercise 9: Generate Tuple Pattern
Write a function called generate_tuples that takes an integer n and returns a list of tuples as shown in the example: for n=5, it should return [(1,), (1,2), (1,2,3), (1,2,3,4), (1,2,3,4,5)].
Generate Tuple Pattern
def generate_tuples(n): result = [] for i in range(1, n + 1): result.append(tuple(range(1, i + 1))) return result
n = int(input())result = generate_tuples(n)print(result)Exercise 10: Custom Zip Function
Implement a custom zip function called custom_zip that takes an arbitrary number of iterables as arguments (using *args) and returns a list of tuples, where each tuple contains the i-th element from each iterable. The function should stop when the shortest iterable is exhausted.
Custom Zip Function
def custom_zip(*args): if not args: return []
min_length = min(map(len, args)) result = []
for i in range(min_length): tuple_items = tuple(map(lambda x: x[i], args)) result.append(tuple_items)
return resultExercise 11: Counter Closure
Write a function called counter that takes a start value, creates an internal counter from the start, and returns a function. Each time the returned function is invoked, it returns the current counter value and then increments it.
Counter Closure
def counter(start): count = start def increment(): nonlocal count current = count count += 1 return current return incrementExercise 12: Once Function
Write a function called once that takes a function fn and returns a new function. The returned function should be identical to the original function except that it ensures fn is called at most once. The first time it’s called, it should return the same result as fn. Every subsequent time it’s called, it should return None. The function should work with functions that have no parameters, multiple parameters, keyword arguments, or both.
Once Function
def once(fn): called = False result = None
def wrapper(*args, **kwargs): nonlocal called, result if not called: result = fn(*args, **kwargs) called = True return result return None
return wrapperExercise 13: Function Composition
Write a function called compose that takes multiple functions as input (each only taking one argument), and returns a new function which is the composition of them. The composition should apply functions from right to left: compose(f, g, h)(x) = f(g(h(x))).
Function Composition
def compose(*functions): def composed(x): result = x for func in reversed(functions): result = func(result) return result return composedExercise 14: Function Currying
Write a function called curry that takes a function fn and returns a curried version. A curried function can be called with one argument at a time. For example, if add(a, b, c) adds three numbers, curried_add = curry(add) allows curried_add(1)(2)(3) to return 6.
Hint: To get the number of arguments a function expects, you can use fn.__code__.co_argcount. This accesses the function’s code object which contains information about the function’s parameters.
Function Currying
def curry(fn): def curried(*args): if len(args) >= fn.__code__.co_argcount: return fn(*args) else: def partial(*more_args): return curried(*(args + more_args)) return partial return curriedExercise 15: Common Elements
Write a function called common that takes an arbitrary number of lists and tuples (using *args), and returns a list of all common elements found in all of them. The elements returned should be unique (no duplicates).
Common Elements
def common(*args): if not args: return []
# Convert all to sets and find intersection sets = [set(iterable) for iterable in args] result_set = sets[0]
for s in sets[1:]: result_set = result_set & s
return sorted(list(result_set))Exercise 16: Custom Map Function
Implement a custom map function called custom_map that takes a function and one or more iterables, and applies the function to corresponding elements from each iterable. It should return a list of results.
Custom Map Function
def custom_map(func, *iterables): if not iterables: return []
min_length = min(map(len, iterables)) result = []
for i in range(min_length): args = tuple(map(lambda it: it[i], iterables)) result.append(func(*args))
return resultExercise 17: Custom Filter Function
Implement a custom filter function called custom_filter that takes a function (or None) and an iterable, and returns a list of elements for which the function returns True (or truthy values if function is None).
Custom Filter Function
def custom_filter(func, iterable): if func is None: func = bool
result = [] for item in iterable: if func(item): result.append(item) return resultExercise 18: Memoization Decorator
Write a function called memoize that takes a function and returns a memoized version. The memoized function should cache results based on arguments, so if the same arguments are passed again, it returns the cached result instead of recalculating.
Memoization Decorator
def memoize(fn): cache = {}
def memoized(*args): key = args if key not in cache: cache[key] = fn(*args) return cache[key]
return memoized