7.9. ExercisesΒΆ

  1. In Robert McCloskey’s book Make Way for Ducklings, the names of the ducklings are Jack, Kack, Lack, Mack, Nack, Ouack, Pack, and Quack. This loop tries to output these names in order. Save your answer in a variable named words and make sure that this value doesn’t get overwritten later in your program.

    Use map plus a helper function to solve this problem.

    prefixes = "JKLMNOPQ"
    suffix = "ack"
    
    words = [first + suffix for first in prefixes]
    

    Of course, that’s not quite right because Ouack and Quack are misspelled. Can you fix it?

  1. Use map and filter to filter the hours table to include only managers. In SQL this would be performed using SELECT and WHERE. Hint: Start by creating a list of the names of all managers.

    hours = [["Alice", 43],
               ["Bob", 37],
               ["Fred", 15]]
    titles = [["Alice", "Manager"],
              ["Betty", "Consultant"],
              ["Bob", "Assistant"]]
    
  1. Use map, len, and filter to decide if the following tables contain a manager that worked at least 40 hours.

    hours = [["Alice", 43],
               ["Bob", 37],
               ["Fred", 15]]
    titles = [["Alice", "Manager"],
              ["Betty", "Consultant"],
              ["Bob", "Assistant"]]
    
  1. Use some combination of map and filter to create a sequence of functions that combine to average two matrices. A complete solution will provide functions for each level of abstraction.

  1. Create a function that takes a value n as input and constructs a multiplication table for whole numbers up to \(n\). Use some combination of map, filter and reduce to solve this problem.

    In [1]: row = lambda j, n: list(map(lambda i: j*i, range(1, n+1)))
    
    In [2]: table = lambda n: list(map(lambda j: row(j, n), range(1, n+1)))
    
    In [3]: table(12)
    Out[3]: 
    [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
     [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24],
     [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36],
     [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48],
     [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60],
     [6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72],
     [7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84],
     [8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96],
     [9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99, 108],
     [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
     [11, 22, 33, 44, 55, 66, 77, 88, 99, 110, 121, 132],
     [12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144]]
    
  1. Print out a neatly formatted multiplication table, up to 12 x 12. You should do this by constructing a string. For full credit, each column should be right-justified and your solution should include only map and helper functions. (You are allowed to use the strings join and rjust methods in your helper functions) Hint: Write a lambda function pads a number with the right number of spaces. Use some combination of map, filter and reduce to solve this problem.
  1. Write a function that will return the number of digits in an integer.

    Use reduce to solve thie problem.

    In [4]: from functools import reduce
    
    In [5]: numDigits = lambda n: reduce(lambda acc, ch: acc + 1, str(n), 0)
    
    In [6]: numDigits(50)
    Out[6]: 2
    
    In [7]: numDigits(20000)
    Out[7]: 5
    
    In [8]: numDigits(1)
    Out[8]: 1
    
  1. Write a function named remove_char that removes all occurrences of a given letter from a string. Do not use the replace string method.

    Use reduce to solve this problem.

  1. Write a function called str_join that takes two arguments s (a string) and L (a list of strings) and returns the equivalent of s.join(L). Use reduce to solve this problem without using the string join method.
  1. Write a function that recognizes palindromes. Use reduce to solve thie problem. Hint: Use reversed and zip.

    In [9]: from functools import reduce
    
    In [10]: is_palindrome = lambda mystr: reduce(lambda acc, tup: acc and tup[0] == tup[1], zip(mystr,reversed(mystr)), True)
    
    In [11]: is_palindrome('abba')
    Out[11]: True
    
  1. Write a function called has_vowel that takes a string as input and returns True if the string contains a vowel ('aeiou' ignore 'y') and False otherwise. Use reduce to perform this task.
  1. Write a Python function that takes n and m as input and returns the maximum value of a the list of n random integers between 0 and m. (Note:. there is a builtin function named max.)

    Use map to generating the random sequence and reduce to find the max.

    In [12]: from random import randint
    
    In [13]: from functools import reduce
    
    In [14]: from itertools import repeat
    
    In [15]: rand_seq = lambda n, m: map(randint, repeat(0, n), repeat(m, n))
    
    In [16]: update_max = lambda cur_max, item: item if item > cur_max else cur_max
    
    In [17]: rand_max = lambda n, m: reduce(update_max, rand_seq(n, m))
    
    In [18]: rand_max(10,5)
    Out[18]: 4
    
  1. Write a function called mean_normal(n, m, sd) that computes the mean of n randomly selected values taken from a normal distribution with mean m and standard deviation sd. Use map and normalvariate (from the random module) to generate the sequence and use reduce to compute the mean.

  1. Write a function sum_of_squares(xs) that computes the sum of the squares of the numbers in the list xs. For example, sum_of_squares([2, 3, 4]) should return 4+9+16 which is 29.

    Use reduce to solve this problem.

  1. Write a function to count how many odd numbers are in a list.

    Use some combination of map, filter and reduce to solve this problem.

    In [19]: import random
    
    In [20]: countOdd = lambda lst: reduce(lambda a, i: a + 1, filter(lambda n: n % 2 == 1, lst))
    
    # make a random list to test the function
    In [21]: lst = [random.randint(0, 1000) for i in range(100)]
    
    In [22]: countOdd(lst)
    Out[22]: 194
    
  1. Write a function called sum_even that sums up all the even numbers in a list. Use some combination of map, filter and reduce to solve this problem.

  1. Sum up all the negative numbers in a list. Use some combination of map, filter and reduce to solve this problem.

    In [23]: import random
    
    In [24]: from operator import add
    
    In [25]: sumNegatives = lambda lst: reduce(add, filter(lambda n: n < 0, lst))
    
    In [26]: lst = [random.randint(-1000, 1000) for i in range(100)]
    
    In [27]: sumNegatives(lst)
    Out[27]: -24819
    
  1. Write a function called num_greater_5 that counts how many words in a list have a more than than 5 characters. Use some combination of map, filter and reduce to solve this problem.

  1. The following sample file called studentdata.txt contains one line for each student in an imaginary class. The student’s name is the first thing on each line, followed by some exam scores. The number of scores might be different for each student.

    joe 10 15 20 30 40
    bill 23 16 19 22
    sue 8 22 17 14 32 17 24 21 2 9 11 17
    grace 12 28 21 45 26 10
    john 14 32 25 16 89
    

    Using the text file studentdata.txt (shown in above) write a program that creates a new data table that contains the students’ names along with the minimum and maximum score for each student.

    Complete this exercise using map, filter and/or reduce. Note: For full credit you will need to also implement max and min using reduce.

  1. SeanLahman.com provides a database of baseball statistics. Download, unzip and extract the file titled Batting.csv.

    Write each of the following functions and apply them to the related task. Write all of your functions and expressions only using funcitonal tools like with_iter, map, filter, reduce, compose and/or pipe.

    1. Write a function that takes a year and table of batting data as input and returns the average number of runs scored in that year. Call this function average_runs_year.
    2. Write a function takes a list of years and a table of batting data and returns of list of tuples of the form (year, averages_runs). Call this function average_runs_years Use a list comprehension and the function from the last step.
    3. Write a program that includes the above functions and reads Batting.csv and compute the average number of runs for the following years: 1900, 1910, ..., 2000, 2010. Assume that the Batting.csv file is the same directory as your program.
  1. The toolz library includes a function called complement, which takes a Boolean function as input and returns a Boolean function that is the logical opposite.

    For example, complement(is_odd) would be equivalent to is_even and complement(less_than_5) would be equivalent to at_least_5.

    In [28]: from toolz import complement
    
    In [29]: is_odd = lambda n: n % 2 == 1
    
    In [30]: is_odd(5)
    Out[30]: True
    
    In [31]: is_odd(4)
    Out[31]: False
    
    In [32]: is_even = complement(is_odd)
    
    In [33]: is_even(5)
    Out[33]: False
    
    In [34]: is_even(4)
    Out[34]: True
    
    In [35]: less_than_5 = lambda n: n < 5
    
    In [36]: less_than_5(2)
    Out[36]: True
    
    In [37]: less_than_5(22)
    Out[37]: False
    
    In [38]: at_least_5 = complement(less_than_5)
    
    In [39]: at_least_5(2)
    Out[39]: False
    
    In [40]: at_least_5(22)
    Out[40]: True
    

    Implement your own version of this function named my_complement.

  1. The toolz library includes a function called do that is useful when performing side effects. We saw do in action in Chapter 5 when printing a sequence out to a file. The function do(func, x) takes a (likely side-effecting) function func and a value x as inputs. First, func is called with x as an argument then the original x is returned. Note that the any value returned by func(x) is discarded.

    For example, we can use do to say hello to a given value (with print) and then return that value.

    In [41]: from toolz import do
    
    In [42]: say_hello = lambda x: print("Hello", x)
    
    In [43]: do(say_hello, 4)
    Hello 4
    Out[43]: 4
    
    In [44]: list(map(lambda x: do(say_hello, x), [1,2,3]))
    Hello 1
    Hello 2
    Hello 3
    Out[44]: [1, 2, 3]
    

    Implement a version of this function named my_do.

  1. The toolz library includes a function called juxt that takes a sequence of functions that returns a function. The new function will apply each of the original functions to any input and return a tuple containing the results.

    For example, suppose that we want to make a function that (a) adds 1, (b) doubles and (c) squares any input. This is accomplished using juxt as follows.

    In [45]: from toolz import juxt
    
    In [46]: f = juxt(lambda i: i + 1,
       ....:          lambda i: 2*i,
       ....:          lambda i: i**2)
       ....: 
    
    In [47]: f(3)
    Out[47]: (4, 6, 9)
    
    In [48]: assert f(5) == (5 + 1, 2*5, 5**2)
    

    Implement a version of this function named my_juxt.

  1. Write and implementation of pipe called my_pipe that takes an expression x as the first argument and a sequence of functions f1, f2, ... as the remaining arguments and applies each function to the result of x, from left to right. Your function should pass the following assertions.
  1. Implement a version of thread_first called my_thread_first that threads a value through the first argument of each of a list of functions. If any of the functions take more than one argument, these arguments can be given along with the function in a tuple. For example, my_thread_first(5, f, g) should be equivalent to g(f(5)) and my_thread_first(5, (add, 1), (pow, 2)) expands to pow(add(5,1), 2). Note that each expression goes in the first argument of the next function call.
  1. Download, unzip and extract the file titled Salaries.csv and AllstarFull.csv from seanlahman.com .

    Write a program that computes the average salary of all players in the all star game in for each year between 2000 and 2010. Write all of your functions and expressions only using funcitonal tools like with_iter, map, filter, reduce, compose and/or pipe. Hint: You will want to use groupby in your solution.

  1. Download, unzip and extract the file titled Master.csv and BattingPost.csv. from seanlahman.com

    Write a program that computes the total runs scored in the post season by all players from from each state (all time). Write all of your functions and expressions only using funcitonal tools like with_iter, map, filter, reduce, compose and/or pipe. Hint: You will want to use groupby in your solution.

Next Section - Lab 1 - Closures and Scope