""" Homework 2: Higher Order Functions and Recursion """ HW_SOURCE_FILE = 'hw02.py' from operator import add, mul square = lambda x: x * x identity = lambda x: x triple = lambda x: 3 * x increment = lambda x: x + 1 ###################### # Required Questions # ###################### # Q1 def make_adder(n): """Return a function that takes an argument K and returns N + K. >>> add_three = make_adder(3) >>> add_three(1) + add_three(2) 9 >>> make_adder(1)(2) 3 """ "*** YOUR CODE HERE ***" return 'REPLACE ME' # Q2 def double_eights(n): """ Returns whether or not n has two digits in row that are the number 8. Assume n has at least two digits in it. >>> double_eights(1288) True >>> double_eights(880) True >>> double_eights(538835) True >>> double_eights(284682) False >>> double_eights(588138) True >>> double_eights(78) False >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'double_eights', ['While', 'For']) True """ "*** YOUR CODE HERE ***" # Q3 def product(n, term): """Return the product of the first n terms in a sequence. n -- a positive integer term -- a function that takes one argument >>> product(3, identity) # 1 * 2 * 3 6 >>> product(5, identity) # 1 * 2 * 3 * 4 * 5 120 >>> product(3, square) # 1^2 * 2^2 * 3^2 36 >>> product(5, square) # 1^2 * 2^2 * 3^2 * 4^2 * 5^2 14400 >>> product(3, increment) # (1+1) * (2+1) * (3+1) 24 >>> product(3, triple) # 1*3 * 2*3 * 3*3 162 >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'product', ['Recursion']) True """ "*** YOUR CODE HERE ***" # The identity function, defined using a lambda expression! identity = lambda k: k def factorial(n): """Return n factorial for n >= 0 by calling product. >>> factorial(4) 24 >>> factorial(6) 720 >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'factorial', ['Recursion', 'For', 'While']) True """ "*** YOUR CODE HERE ***" # Q4 def summation(n, term): """Return the sum of the first n terms in the sequence defined by term. Implement using recursion! >>> summation(5, lambda x: x * x * x) # 1^3 + 2^3 + 3^3 + 4^3 + 5^3 225 >>> summation(9, lambda x: x + 1) # 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 54 >>> summation(5, lambda x: 2**x) # 2^1 + 2^2 + 2^3 + 2^4 + 2^5 62 >>> # Do not use while/for loops! >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'summation', ... ['While', 'For']) True """ assert n >= 1 "*** YOUR CODE HERE ***" # Q5 def accumulate(combiner, base, n, term): """Return the result of combining the first n terms in a sequence and base. The terms to be combined are term(1), term(2), ..., term(n). combiner is a two-argument commutative function. >>> accumulate(add, 0, 5, identity) # 0 + 1 + 2 + 3 + 4 + 5 15 >>> accumulate(add, 11, 5, identity) # 11 + 1 + 2 + 3 + 4 + 5 26 >>> accumulate(add, 11, 0, identity) # 11 11 >>> accumulate(add, 11, 3, square) # 11 + 1^2 + 2^2 + 3^2 25 >>> accumulate(mul, 2, 3, square) # 2 * 1^2 * 2^2 * 3^2 72 """ "*** YOUR CODE HERE ***" def summation_using_accumulate(n, term): """Returns the sum of term(1) + ... + term(n). The implementation uses accumulate. >>> summation_using_accumulate(5, square) 55 >>> summation_using_accumulate(5, triple) 45 >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'summation_using_accumulate', ... ['Recursion', 'For', 'While']) True """ "*** YOUR CODE HERE ***" def product_using_accumulate(n, term): """An implementation of product using accumulate. >>> product_using_accumulate(4, square) 576 >>> product_using_accumulate(6, triple) 524880 >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'product_using_accumulate', ... ['Recursion', 'For', 'While']) True """ "*** YOUR CODE HERE ***" # Q6 def filtered_accumulate(combiner, base, pred, n, term): """Return the result of combining the terms in a sequence of N terms that satisfy the predicate pred. combiner is a two-argument function. If v1, v2, ..., vk are the values in term(1), term(2), ..., term(N) that satisfy pred, then the result is base combiner v1 combiner v2 ... combiner vk (treating combiner as if it were a binary operator, like +). The implementation uses accumulate. >>> filtered_accumulate(add, 0, lambda x: True, 5, identity) # 0 + 1 + 2 + 3 + 4 + 5 15 >>> filtered_accumulate(add, 11, lambda x: False, 5, identity) # 11 11 >>> filtered_accumulate(add, 0, odd, 5, identity) # 0 + 1 + 3 + 5 9 >>> filtered_accumulate(mul, 1, greater_than_5, 5, square) # 1 * 9 * 16 * 25 3600 >>> # Do not use while/for loops or recursion >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'filtered_accumulate', ... ['While', 'For', 'Recursion']) True """ def combine_if(x, y): "*** YOUR CODE HERE ***" return accumulate(combine_if, base, n, term) def odd(x): return x % 2 == 1 def greater_than_5(x): return x > 5 # Q7 def compose1(f, g): """Return a function h, such that h(x) = f(g(x)).""" def h(x): return f(g(x)) return h def make_repeater(f, n): """Return the function that computes the nth application of f. >>> add_three = make_repeater(increment, 3) >>> add_three(5) 8 >>> make_repeater(triple, 5)(1) # 3 * 3 * 3 * 3 * 3 * 1 243 >>> make_repeater(square, 2)(5) # square(square(5)) 625 >>> make_repeater(square, 4)(5) # square(square(square(square(5)))) 152587890625 >>> make_repeater(square, 0)(5) 5 """ "*** YOUR CODE HERE ***" ################### # Extra Questions # ################### # Q8 from operator import sub, mul def make_anonymous_factorial(): """Return the value of an expression that computes factorial. >>> make_anonymous_factorial()(5) 120 >>> from construct_check import check >>> check(HW_SOURCE_FILE, 'make_anonymous_factorial', ['Assign', 'AugAssign', 'FunctionDef', 'Recursion']) True """ return 'YOUR_EXPRESSION_HERE'