The logician Alonzo Church invented a system of representing non-negative integers entirely using functions. The purpose was to show that functions are sufficient to describe all of number theory: if we have functions, we do not need to assume that numbers exist, but instead we can invent them.
Your goal in this problem is to rediscover this representation known as Church numerals. Here are the definitions of zero, as well as a function that returns one more than its argument:
First, define functions one and two such that they have the same behavior as successor(zero) and successsor(successor(zero)) respectively, but do not call successor in your implementation.
Next, implement a function church_to_int that converts a church numeral argument to a regular Python integer.
Finally, implement functions add_church, mul_church, and pow_church that perform addition, multiplication, and exponentiation on church numerals.
defone(f): """Church numeral 1: same as successor(zero)""" "*** YOUR CODE HERE ***"
deftwo(f): """Church numeral 2: same as successor(successor(zero))""" "*** YOUR CODE HERE ***"
three = successor(two)
defchurch_to_int(n): """Convert the Church numeral n to a Python integer. >>> church_to_int(zero) 0 >>> church_to_int(one) 1 >>> church_to_int(two) 2 >>> church_to_int(three) 3 """ "*** YOUR CODE HERE ***"
defadd_church(m, n): """Return the Church numeral for m + n, for Church numerals m and n. >>> church_to_int(add_church(two, three)) 5 """ "*** YOUR CODE HERE ***"
defmul_church(m, n): """Return the Church numeral for m * n, for Church numerals m and n. >>> four = successor(three) >>> church_to_int(mul_church(two, three)) 6 >>> church_to_int(mul_church(three, four)) 12 """ "*** YOUR CODE HERE ***"
defpow_church(m, n): """Return the Church numeral m ** n, for Church numerals m and n. >>> church_to_int(pow_church(two, three)) 8 >>> church_to_int(pow_church(three, two)) 9 """ "*** YOUR CODE HERE ***"
The recursive factorial function can be written as a single expression by using a conditional expression.
1 2 3
>>> fact = lambda n: 1 if n == 1 else mul(n, fact(sub(n, 1))) >>> fact(5) 120
However, this implementation relies on the fact (no pun intended) that fact has a name, to which we refer in the body of fact. To write a recursive function, we have always given it a name using a def or assignment statement so that we can refer to the function within its own body. In this question, your job is to define fact recursively without giving it a name!
Write an expression that computes n factorial using only call expressions, conditional expressions, and lambda expressions (no assignment or def statements). Note in particular that you are not allowed to use make_anonymous_factorial in your return expression. The sub and mul functions from the operator module are the only built-in functions required to solve this problem:
1 2 3 4 5 6 7 8 9 10 11 12 13
from operator import sub, mul
defmake_anonymous_factorial(): """Return the value of an expression that computes factorial. >>> make_anonymous_factorial()(5) 120 >>> from construct_check import check >>> # ban any assignments or recursion >>> check(HW_SOURCE_FILE, 'make_anonymous_factorial', ['Assign', 'AugAssign', 'FunctionDef', 'Recursion']) True """ return'YOUR_EXPRESSION_HERE'
solution
1 2 3 4 5 6 7 8 9
from operator import sub, mul
defmake_anonymous_factorial(): return (lambda f: lambda k: f(f, k))(lambda f, k: k if k == 1else mul(k, f(f, sub(k, 1)))) # Alternate solution1: # return (lambda f: f(f))(lambda f: lambda x: 1 if x == 0 else x * f(f)(x - 1)) # Alternate solution2: # from functools import reduce # return lambda n:reduce(mul, range(1, n + 1))
solution2 感觉比较取巧,前两种解法又实在难以理解。。
Lab07
Q6: Number of Trees
problem
How many different possible full binary tree (each node has 2 branches or 0, but never 1) structures exist that have exactly n leaves?
For those interested in combinatorics, this problem does have a closed form solution):
defnum_trees(n): """Returns the number of unique full binary trees with exactly n leaves. E.g., """ if n == 1or n == 2: return1 # catalan number ans = 0 for i inrange(1, n): ans += num_trees(i) * num_trees(n - i) return ans
化简后的答案
1 2 3
if n == 1 or n == 2: return 1 return num_trees(n-1)*2*(2*n-3)//n