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.)

Asked By: Deler

||

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

Answered By: Frank Yellin

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
Answered By: Ashgabyte

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.

Answered By: Kelly Bundy
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.