Python: calc n factorial only use call expressions, conditional expressions, and lambda expressions
Question:
This is an interesting question from online.
The full question is:
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 it recursively without giving it a name!
Write an expression to complete the function make_anonymous_factorial(),which 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.
e.g.
>>> make_anonymous_factorial( )(5)
120
Here is my solution:
from operator import sub, mul
def make_anonymous_factorial():
from functools import reduce
return lambda n:reduce(mul, range(1, n + 1))
However, as the question described,The sub and mul functions from the operator module are the only built-in functions required to solve this problem, since I used reduce( ), I don’t think it is a suitable answer.
Is there a better solution?
(The question is from cs61a summer 2020 HW03, Q6, and here is the link. It’s the last question which is on the bottom of the page.)
Answers:
Here is a good explanation of the Y combinator. Its example is writing factorial in Python!
https://lptk.github.io/programming/2019/10/15/simple-essence-y-combinator.html
If lambda is OK, this code works:
f = lambda x: x * f(x - 1) if x > 1 else 1
# example
print(f(5)) # 120
Without assignment using reduce from functools:
from functools import reduce
print(reduce(lambda x, y: x * y, list(range(1, 5 + 1)))) # 120
After reading the article Frank mentioned up to the point where it talks about a function getting itself as argument, I tried that (Try it online!):
from operator import sub, mul
def make_anonymous_factorial():
return (lambda f: lambda n: f(n, f))(
lambda n, f: mul(n, f(sub(n, 1), f)) if n else 1
)
print(make_anonymous_factorial()(5))
The innermost lambda n, f:
is the real factorial computer, and it’ll get itself as second argument. That is organized by the outer two lambdas. The lambda n:
is the one I return, it calls the real factorial with n
and itself.
This is an interesting question from online.
The full question is:
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 it recursively without giving it a name!
Write an expression to complete the function make_anonymous_factorial(),which 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.
e.g.
>>> make_anonymous_factorial( )(5)
120
Here is my solution:
from operator import sub, mul
def make_anonymous_factorial():
from functools import reduce
return lambda n:reduce(mul, range(1, n + 1))
However, as the question described,The sub and mul functions from the operator module are the only built-in functions required to solve this problem, since I used reduce( ), I don’t think it is a suitable answer.
Is there a better solution?
(The question is from cs61a summer 2020 HW03, Q6, and here is the link. It’s the last question which is on the bottom of the page.)
Here is a good explanation of the Y combinator. Its example is writing factorial in Python!
https://lptk.github.io/programming/2019/10/15/simple-essence-y-combinator.html
If lambda is OK, this code works:
f = lambda x: x * f(x - 1) if x > 1 else 1
# example
print(f(5)) # 120
Without assignment using reduce from functools:
from functools import reduce
print(reduce(lambda x, y: x * y, list(range(1, 5 + 1)))) # 120
After reading the article Frank mentioned up to the point where it talks about a function getting itself as argument, I tried that (Try it online!):
from operator import sub, mul
def make_anonymous_factorial():
return (lambda f: lambda n: f(n, f))(
lambda n, f: mul(n, f(sub(n, 1), f)) if n else 1
)
print(make_anonymous_factorial()(5))
The innermost lambda n, f:
is the real factorial computer, and it’ll get itself as second argument. That is organized by the outer two lambdas. The lambda n:
is the one I return, it calls the real factorial with n
and itself.