Домашнее задание № 2
Для выполнения задания найди ссылку-приглашение в онлайн чате, получи доступ к репозиторию с файлом-заготовкой и заполни пропуски в нём. Фиксируй изменения (делай коммиты) после решения каждой задачи. Оставь название файла неизменным, иначе робот-проверятель не найдёт твои ответы. Отправить решения на GitHub нужно до истечения установленного срока. |
Некоторые доктесты будут ссылаются на эти функции.
from operator import add, mul, sub
square = lambda x: x * x
identity = lambda x: x
triple = lambda x: 3 * x
increment = lambda x: x + 1
После завершения работы над каждым вопросом требуется фиксировать изменения (делать коммит), сопровождая его вменяемым описанием сделанного, например:
Так же не возбраняется в любое время проталкивать изменения на GitHub:
|
Вопрос 1
В лекции «Функции высшего порядка» была рассмотрена функция summation(n, term)
, результат её выполнения — term(1) + … + term(n)
. Напиши похожую функцию product(n, term)
, которая возвращает term(1) * … * term(n)
. Использовать рекурсию нельзя.
def product(n, term):
"""
Возвращает произведение первых n членов (terms) последовательности.
Аргументы:
n (int): количество перемножаемых элементов последовательности.
term (func): функция одного аргумента.
>>> 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
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
Теперь покажи, как определить функцию factorial
в одну строчку, используя функцию product
.
def factorial(n):
"""
Возвращает факториал n при n >= 0, используя функцию product.
>>> factorial(4) # 4 * 3 * 2 * 1
24
>>> factorial(6) # 6 * 5 * 4 * 3 * 2 * 1
720
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
Вопрос 2
На самом деле и summation
, и product
— частные случаи более общей функции accumulate
(накопление).
def accumulate(combiner, base, n, term):
"""
Возвращает результат объединения (combining) первых n членов последовательности.
>>> 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
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
Функция accumulate
принимает следующие аргументы:
-
term
иn
— те же, что в функцияхsummation
иproduct
; -
combiner
— функция двух аргументов, которая определяет, как один член объединяется с другим; -
base
— значение, с которого начинается накопление.
Например, accumulate(add, 11, 3, square)
— это 11 + square(1) + square(2) + square(3) = 25
Можешь считать, что combiner обладает ассоциативностью и коммутативностью, то есть combiner(a, combiner(b, c)) == combiner(combiner(a, b), c) и combiner(a, b) == combiner(b, a) для всех a , b и c . Однако нельзя считать, что поведение combiner выбирается из фиксированного набора действий.
|
Реализуй accumulate
, а потом покажи, как summation
и product
могут быть определены через вызов accumulate
.
def summation_using_accumulate(n, term):
"""
Возвращает сумму term(1) + ... + term(n). Реализация с использованием accumulate.
>>> summation_using_accumulate(5, square)
55
>>> summation_using_accumulate(5, triple)
45
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
def product_using_accumulate(n, term):
"""
Возвращает произведение term(1) * ... * term(n). Реализация с использованием accumulate.
>>> product_using_accumulate(3, lambda x: (x+1)*(x+5)*x)
48384
>>> product_using_accumulate(4, square)
576
>>> product_using_accumulate(6, triple)
524880
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
Вопрос 3
Допиши функцию double
, которая принимает одну функцию, а возвращает другую функцию, применяющую первоначальную функцию дважды. Например, если функция inc
возвращает увеличенное на единицу значение аргумента, то результат double(inc)
должен быть функцией, увеличивающей значение аргумента на два.
def double(f):
"""
Возвращает функцию, применяющую f дважды.
Аргументы:
f (func): функция одного аргумента.
>>> double(square)(2)
16
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
Вопрос 4
Напиши функцию make_repeater
, чтобы вызов make_repeater(f, n)(x)
возвращал результат f(f(…f(x)…))
, в котором f
применяется n
раз. То есть make_repeater(f, n)
должен вернуть новую функцию одного аргумента. Например, результат make_repeater(square, 3)(42)
можно представить как square(square(square(42)))
.
def make_repeater(f, n):
"""Возвращает функцию, применяющую f n раз.
Аргументы:
f (func): функция одного аргумента.
n (int): количество применений функции 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
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
В качестве дополнительно упражнения реализуй
|
Вопрос 5* (для самых умных)
Учёный-логик Алонзо Чёрч изобрел систему представления неотрицательных чисел исключительно с помощью функций. Цель состояла в том, чтобы показать, что функций достаточно для описания всей теории чисел: если у нас есть функции, нам не нужно полагать, что числа существуют — вместо этого мы можем их сконструировать.
Задачи «для самых умных» опциональны. Попробуй порешать. Не выходит — и не надо. |
Твоя же цель состоит в освоении представления, известного как «Числа Чёрча». Вот определение для нулевого числа Чёрча zero
и функции successor
, увеличивающей число Чёрча на единицу:
def zero(f):
return lambda x: x
def successor(n):
return lambda f: lambda x: f(n(f)(x))
Определи единицу one
и двойку two
так, чтобы их поведение было successor(zero)
и successsor(successor(zero))
соответственно. Однако не используй successor
в своём коде.
Далее определи функцию church_to_int
— преобразование числа Чёрча в обычное целочисленное представление.
Наконец, реализуй для чисел Чёрча сложение add_church
, умножение mul_church
и возведение в степень pow_church
.
def one(f):
"""Число Чёрча 1."""
"*** ТВОЙ КОД ЗДЕСЬ ***"
def two(f):
"""Число Чёрча 2."""
"*** ТВОЙ КОД ЗДЕСЬ ***"
three = successor(two)
def church_to_int(n):
"""Преобразует число Чёрча n в целое число Python.
>>> church_to_int(zero)
0
>>> church_to_int(one)
1
>>> church_to_int(two)
2
>>> church_to_int(three)
3
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
def add_church(m, n):
"""Возвращает число Чёрча m + n для чисел Чёрча m и n.
>>> church_to_int(add_church(two, three))
5
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
def mul_church(m, n):
"""Возвращает число Чёрча m * n для чисел Чёрча m и n.
>>> four = successor(three)
>>> church_to_int(mul_church(two, three))
6
>>> church_to_int(mul_church(three, four))
12
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
def pow_church(m, n):
"""Возвращает число Чёрча m ** n для чисел Чёрча m и n.
>>> church_to_int(pow_church(two, three))
8
>>> church_to_int(pow_church(three, two))
9
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
Не забудь отправить работу на проверку:
|