Welcome, guest | Sign In | My Account | Store | Cart

One Liner Factorial function This code gets factorial of a number and for negative numbers returns 1

Python, 6 lines
1
2
3
4
5
6
#calculates factorial and for n <=1 n! = 1
fac = lambda n:n-1 + abs(n-1)and fac(n-1)*n or 1L
#another version
fac = lambda n:[1,0][n>0] or fac(n-1)*n
#and another
fac = lambda n:reduce(lambda a,b:a*(b+1),range(n),1)

The recursive implementation of factorial is easy but using lambda keyword of python it becomes a bit tough as we can't use conditional if else in lambda. If a user wants to return a factorial function on the fly using lambda than this may be the solution

9 comments

Patrick O'Brien 22 years, 5 months ago  # | flag

Larger Factorials. This function can be improved to handle larger factorials by changing the code to use long integers:

f = lambda n:n-1 + abs(n-1) and f(n-1)*long(n) or 1
panoplos cechnokiv 22 years, 3 months ago  # | flag

No need for the complexity... Just do the following:

f = lambda n: n and f(n-1)*long(n) or 1

panoplos cechnokiv 22 years, 3 months ago  # | flag

Ignore this... This doesn't handle negative values. =)

-- gently inserting foot into mouth...

Chema Cortes 21 years, 12 months ago  # | flag

functional solution. I want to point that the third formula is a functional solution (non recursive). A more concise formula:

fac=lambda n: [1,0][n>0] or reduce(lambda x,y: x*y, xrange(1,n+1))
Chema Cortes 21 years, 12 months ago  # | flag

functional solution. Or better:

f=lambda n: n&lt;=0 or reduce(lambda a,b: a*b,xrange(1,n+1))
Carl Bray 21 years, 9 months ago  # | flag

Requires long conversions. Trying to get the factorial of 20 causes an overflow.

lambda n: n&lt;=0 or reduce(lambda a,b: a*b,xrange(1,n+1))
OverflowError: integer multiplication

I've amended the function to handle this.

lambda n: n&lt;=0 or reduce(lambda a,b: long(a)*long(b),xrange(1,n+1))
Frank P Mora 18 years, 8 months ago  # | flag

A one-line numeric function using list comprehensions.

>>> f= lambda n: [[[j for j in (j*i,)][0] for i in range(2,n+1)][-1] for j in (1,)][0]
>>> f(5)
120

If I were going to use reduce which might be removed from python I would
use it with the operator mul. Long ints are automatic in Python 2.4.

>>> from operator import mul
>>> f= lambda n: reduce(mul,range(2,n+1))
>>> f(6)
720

Assuming no one would want or need the factorial of anything less than 2.
Frank P Mora 18 years, 8 months ago  # | flag

A better list comprehension expression. Steven Bethard pointed out in recipe 436482 that

f= lambda n: [j for j in [1] for i in range(2,n+1) for j in [j*i]] [-1]

is equivalent but easier to read, write and use.
Simone Leo 16 years, 5 months ago  # | flag

just add initial value... ... And it also handles 0 and 1.

reduce(operator.mul, xrange(2,n+1), 1)
Created by anurag uniyal on Mon, 27 Aug 2001 (PSF)
Python recipes (4591)
anurag uniyal's recipes (12)

Required Modules

  • (none specified)

Other Information and Tasks