The factorial of a number, `n!`, is defined for whole numbers as the product of all integers from `1` to `n`. 

For example, `5!` is `5 * 4 * 3 * 2 * 1 = 120`

Most factorial implementations use a recursive function to determine the value of `factorial(n)`. However, this blows up the stack for large values of `n` - most systems cannot handle stack depths much greater than 2000 levels.

Write an implementation to calculate the factorial of arbitrarily large numbers, *without recursion.*

# Rules

* `n < 0` should return `nil`/  `None`
* `n = 0` should return `1`
* `n > 0` should return `n!`

# Note

Codewars limits the amount of data it will send back and forth, which may introduce a false ceiling for how high of a value of `n` it will accept. All tests use values less than this limit.

Difficulty: introductory

Starter code:

def factorial(n):
	

Solutions:
import math

def factorial(n):
    if n >= 0:
        return math.factorial(n)

import math
def factorial(n):
    return math.factorial(n) if n >= 0 else None

import math
def factorial(n):
    return None if n < 0 else math.factorial(n)

def factorial(n):
    if n < 0:
        return None
    ret = 1
    for i in range(2, n + 1):
        ret *= i
    return ret


factorial = lambda _: __import__('math').factorial(_) if _>=0 else None

from math import factorial as fact

def factorial(n):
    if n >= 0:
        return fact(n)

from math import factorial as f

def factorial(n):
    if n < 0:
        return None
    elif n == 0:
        return 1
    return f(n)

import math

def factorial(n):
    if n < 0 : return None
    if n == 0 or n == 1 : return 1
    if n > 0 : return math.factorial(n)
    #return None


from functools import reduce
def factorial(n):
    if n < 0:
        return None
    if n < 2:
        return 1
    return reduce((lambda x, y: x*y), range(1, n+1))

def factorial(n):

  if n >= 0:
    fact = 1
    for i in range(2, n+1):
      fact *= i
    return fact
  else:
    return None