forked from MIT-Emerging-Talent/ET6-practice-code-review
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #42 from MIT-Emerging-Talent/factorial
factorial function
- Loading branch information
Showing
2 changed files
with
115 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
A module for Computing the factorial of a non-negative integer n. | ||
Module contents: | ||
- factorial: is the product of all positive integers less than or equal to n. | ||
Created on XX XX XX | ||
@author: Saad M. Ashour | ||
""" | ||
|
||
|
||
def factorial(n: int) -> int: | ||
""" | ||
Computes the factorial of a non-negative integer n. | ||
The factorial of a non-negative integer n | ||
is the product of all positive integers less than or equal to n. | ||
Parameters: | ||
n (int): A non-negative integer. | ||
Returns: | ||
int: The factorial of the input integer n. | ||
Raises: | ||
ValueError: If n is negative, as factorial is not defined for negative numbers. | ||
TypeError: If n is not an integer, as factorials are only defined for integers. | ||
Examples: | ||
>>> factorial(0) | ||
1 | ||
>>> factorial(1) | ||
1 | ||
>>> factorial(5) | ||
120 | ||
>>> factorial(3) | ||
6 | ||
""" | ||
# Validate input type and value | ||
if not isinstance(n, int): | ||
raise TypeError("Input must be an integer.") | ||
|
||
if n < 0: | ||
raise ValueError("Factorial is not defined for negative numbers.") | ||
|
||
# Base case for recursion: 0! = 1 | ||
if n == 0 or n == 1: | ||
return 1 | ||
|
||
# Recursive case: n! = n * (n-1)! | ||
return n * factorial(n - 1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Unit tests for factorial function. | ||
@author: Saad M. Ashour | ||
""" | ||
|
||
import unittest | ||
from solutions.factorial import factorial | ||
|
||
|
||
class TestFactorial(unittest.TestCase): | ||
""" | ||
Unit tests for the factorial function. | ||
The factorial function computes the factorial of a non-negative integer using recursion. | ||
These tests verify its correctness for various inputs, | ||
including edge cases, valid cases, and invalid cases. | ||
""" | ||
|
||
|
||
def test_factorial_zero(self): | ||
"""It should evaluate 0 to 1""" | ||
actual = factorial(0) | ||
expected = 1 | ||
self.assertEqual(actual, expected) | ||
|
||
|
||
def test_factorial_one(self): | ||
"""It should evaluate 1 to 1""" | ||
actual = factorial(1) | ||
expected = 1 | ||
self.assertEqual(actual, expected) | ||
|
||
|
||
def test_factorial_positive(self): | ||
"""It should evaluate 5 to 120""" | ||
actual = factorial(5) | ||
expected = 120 | ||
self.assertEqual(actual, expected) | ||
|
||
|
||
def test_factorial_negative(self): | ||
"""factorial of negative integer will raise Error""" | ||
with self.assertRaises(ValueError): | ||
factorial(-1) | ||
|
||
|
||
def test_factorial_non_integer(self): | ||
"""factorial of non integer will raise Error""" | ||
with self.assertRaises(TypeError): | ||
factorial(3.5) | ||
with self.assertRaises(TypeError): | ||
factorial("string") | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |