Solution 1

```
try:
reduce
except NameError:
from functools import reduce
def factorial_terms(a_number):
if a_number < 0:
raise ValueError("Only defined for positive numbers")
return list(range(a_number or 1, 0, -1))
def compute_factorial(terms):
if not terms:
raise ValueError("Terms should have at least one element")
return reduce(lambda a, b: a*b, terms, 1)
def factorial(number):
return compute_factorial(factorial_terms(number))
```

# Function Factorial

The objective of this assignment is to write a factorial function (https://en.wikipedia.org/wiki/Factorial).

In order to do that we'll define 2 helper functions:

`factorial_terms`

: will receive a number and return the list of terms to compute the factorial.`compute_factorial`

: Will receive a list of terms and compute de factorial.

Finally, the `factorial`

function will get a number and, using both helper functions, will compute

the answer.

This assignment is designed to practice the `reduce`

function. But if you think it's getting too complicated, you can just try using a for-loop and check the solution later.

Use the tests to see the complete specification of what you're required to write.

### Test Cases

test factorial terms with an invalid value - Run Test

```
import pytest
def test_factorial_terms_with_an_invalid_value():
"""Should raise an exception if an invalid number is provided"""
with pytest.raises(ValueError):
factorial_terms(-1)
```

test compute factorial with no arguments - Run Test

```
import pytest
def test_compute_factorial_with_no_arguments():
"""Should raise an exception"""
with pytest.raises(ValueError):
compute_factorial([])
```

test factorial for regular integers - Run Test

```
def test_factorial_for_regular_integers():
"""Should return the factorial number for the terms"""
assert factorial(5) == 120
```

test factorial with negative number - Run Test

```
import pytest
def test_factorial_with_negative_number():
"""Should raise an exception"""
with pytest.raises(ValueError):
factorial(-1)
```

test compute factorial for regular integers - Run Test

```
def test_compute_factorial_for_regular_integers():
"""Should return the factorial number for the terms"""
assert compute_factorial([5, 4, 3, 2, 1]) == 120
```

test factorial of zero - Run Test

```
def test_factorial_of_zero():
"""Should return 1"""
assert factorial(0) == 1
```

test compute factorial invoked with one - Run Test

```
def test_compute_factorial_invoked_with_one():
"""Should return 1"""
assert compute_factorial([1]) == 1
```

test factorial terms are generated ok - Run Test

```
def test_factorial_terms_are_generated_ok():
"""Should return the correct terms for a number"""
assert factorial_terms(5) == [5, 4, 3, 2, 1]
```

test factorial terms of zero - Run Test

```
def test_factorial_terms_of_zero():
"""Should return [1]"""
assert factorial_terms(0) == [1]
```