The summation(n, term) function from the higher-order functions lecture adds up term(1) + ... + term(n). Write a similar function called product that returns term(1) * ... * term(n). Do not use recursion.
defproduct(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 ***"
Now, define the factorial function in terms of product in one line.
deffactorial(n):"""Return n factorial for n >= 0 by calling product.>>> factorial(4) # 4 * 3 * 2 * 1 24>>> factorial(6) # 6 * 5 * 4 * 3 * 2 * 1 720>>> from construct_check import check>>> check(HW_SOURCE_FILE, 'factorial', ['Recursion', 'For', 'While']) True """"*** YOUR CODE HERE ***"
Q1: Solution
defproduct(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 ***" product_of_term =1for i inrange(1, n +1): product_of_term *=term(i)return product_of_term
deffactorial(n):"""Return n factorial for n >= 0 by calling product.>>> factorial(4) # 4 * 3 * 2 * 1 24>>> factorial(6) # 6 * 5 * 4 * 3 * 2 * 1 720>>> from construct_check import check>>> check(HW_SOURCE_FILE, 'factorial', ['Recursion', 'For', 'While']) True """"*** YOUR CODE HERE ***"returnproduct(n, lambdai: i)
Q2: Accumulate
Let's take a look at how summation and product are instances of a more general function called accumulate:
defaccumulate(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, associative 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>>> accumulate(lambda x, y: x + y + 1, 2, 3, square) 19 """"*** YOUR CODE HERE ***"
accumulate has the following parameters:
term and n: the same parameters as in summation and product
combiner: a two-argument function that specifies how the current term is combined with the previously accumulated terms.
base: value at which to start the accumulation.
For example, the result of accumulate(add, 11, 3, square) is
11+square(1)+square(2)+square(3)=25
After implementing accumulate, show how summation and product can both be defined as simple calls to accumulate:
defsummation_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 ***"defproduct_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 ***"
Q2: Solution
defaccumulate(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, associative 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>>> accumulate(lambda x, y: x + y + 1, 2, 3, square) 19 """"*** YOUR CODE HERE ***"if n ==0:return baseelse:returncombiner(term(n), accumulate(combiner, base, n -1, term))
defsummation_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 ***"returnaccumulate(lambdax, y: x + y, 0, n, term)defproduct_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 ***"returnaccumulate(lambdax, y: x * y, 1, n, term)
Q3: Make Repeater
Implement a function make_repeater so that make_repeater(f, n)(x) returns f(f(...f(x)...)), where f is applied n times. That is, make_repeater(f, n) returns another function that can then be applied to another argument. For example, make_repeater(square, 3)(42) evaluates to square(square(square(42))). See if you can figure out a reasonable function to return for that case. You may use either loops or recursion in your implementation.
defmake_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) # Yes, it makes sense to apply the function zero times! 5 """"*** YOUR CODE HERE ***"
For an extra challenge, try defining make_repeater using compose1 and your accumulate function in a single one-line return statement.
defcompose1(f,g):"""Return a function h, such that h(x) = f(g(x))."""defh(x):returnf(g(x))return h
Q3: Solution
defmake_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) # Yes, it makes sense to apply the function zero times! 5 """"*** YOUR CODE HERE ***"return (lambdax: x) if n ==0elsecompose1(f, make_repeater(f, n -1))
Q4: Num Sevens
Write a recursive function num_sevens that takes a positive integer n and returns the number of times the digit 7 appears in n.
defnum_sevens(n):"""Returns the number of times 7 appears as a digit of n.>>> num_sevens(3) 0>>> num_sevens(7) 1>>> num_sevens(7777777) 7>>> num_sevens(2637) 1>>> num_sevens(76370) 2>>> num_sevens(12345) 0>>> from construct_check import check>>> check(HW_SOURCE_FILE, 'num_sevens',... ['Assign', 'AugAssign']) True """"*** YOUR CODE HERE ***"if n <10:returnint(n ==7)
Q4: Solution
defnum_sevens(n):"""Returns the number of times 7 appears as a digit of n.>>> num_sevens(3) 0>>> num_sevens(7) 1>>> num_sevens(7777777) 7>>> num_sevens(2637) 1>>> num_sevens(76370) 2>>> num_sevens(12345) 0>>> from construct_check import check>>> check(HW_SOURCE_FILE, 'num_sevens',... ['Assign', 'AugAssign']) True """"*** YOUR CODE HERE ***"returnint(n ==7)if n <10elseint(n %10==7)+num_sevens(n //10)
Q5: Ping-pong
The ping-pong sequence counts up starting from 1 and is always either counting up or counting down. At element k, the direction switches if k is a multiple of 7 or contains the digit 7. The first 30 elements of the ping-pong sequence are listed below, with direction swaps marked using brackets at the 7th, 14th, 17th, 21st, 27th, and 28th elements:
Once the machines take over, the denomination of every coin will be a power of two: 1-cent, 2-cent, 4-cent, 8-cent, 16-cent, etc. There will be no limit to how much a coin can be worth.
Given a positive integer amount, a set of coins makes change for amount if the sum of the values of the coins is amount. For example, the following sets make change for 7:
7 1-cent coins
5 1-cent, 1 2-cent coins
3 1-cent, 2 2-cent coins
3 1-cent, 1 4-cent coins
1 1-cent, 3 2-cent coins
1 1-cent, 1 2-cent, 1 4-cent coins
Thus, there are 6 ways to make change for 7. Write a recursive function count_change that takes a positive integer amount and returns the number of ways to make change for amount using these coins of the future.
defcount_change(amount):"""Return the number of ways to make change for amount.>>> count_change(7) 6>>> count_change(10) 14>>> count_change(20) 60>>> count_change(100) 9828>>> from construct_check import check>>> check(HW_SOURCE_FILE, 'count_change', ['While', 'For']) True """"*** YOUR CODE HERE ***"
Q6: Solution
defcount_change(amount):"""Return the number of ways to make change for amount.>>> count_change(7) 6>>> count_change(10) 14>>> count_change(20) 60>>> count_change(100) 9828>>> from construct_check import check>>> check(HW_SOURCE_FILE, 'count_change', ['While', 'For']) True """"*** YOUR CODE HERE ***"deffind_highest_coin(amount,coin=1,highest=1):if coin <= amount:#coins are power of two, we start with 1 and go onreturnfind_highest_coin(amount, coin *2, highest=coin)return highest#inspired by composing programs, chapter 1.7 and edited the return statementdefcount_partitions(n,m):"""Count the ways to partition n using parts up to m."""if n ==0:return1elif n <0:return0elif m ==0:return0else:returncount_partitions(n-m, m)+count_partitions(n, m//2) highest_coin =find_highest_coin(amount)returncount_partitions(amount, highest_coin)