diff --git a/__init__.py b/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..38743267b Binary files /dev/null and b/requirements.txt differ diff --git a/solutions/basic_calculator/__init__.py b/solutions/basic_calculator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/basic_calculator/calculate.py b/solutions/basic_calculator/calculate.py new file mode 100644 index 000000000..39d6bd597 --- /dev/null +++ b/solutions/basic_calculator/calculate.py @@ -0,0 +1,55 @@ +""" +A module for performing basic arithmetic operations: addition, subtraction, +multiplication, and division. + +Module contents: + - calculate: Performs the specified arithmetic operation on two numbers + +Created on 28/12/2024 +Author: Ana Isabel Murillo +""" + + +def calculate(operation: str, num1: float, num2: float) -> float: + """Performs the specified arithmetic operation on two numbers. + + Parameters: + operation: str, the operation to perform + ('add', 'subtract', 'multiply', 'divide') + num1: float, the first number + num2: float, the second number + + Returns -> float: the result of the arithmetic operation + + Raises: + ValueError: if the operation is invalid or division by zero occurs + + Examples: + >>> calculate('add', 5, 3) + 8.0 + >>> calculate('subtract', 10, 4) + 6.0 + >>> calculate('multiply', 7, 3) + 21.0 + >>> calculate('divide', 9, 3) + 3.0 + >>> calculate('divide', 5, 0) + Traceback (most recent call last): + ... + ValueError: Cannot divide by zero. + """ + if operation == "add": + return num1 + num2 + elif operation == "subtract": + return num1 - num2 + elif operation == "multiply": + return num1 * num2 + elif operation == "divide": + if num2 == 0: + raise ValueError("Cannot divide by zero.") + return num1 / num2 + else: + raise ValueError( + f"Invalid operation '{operation}'. Valid operations are: " + "add, subtract, multiply, divide." + ) diff --git a/solutions/challenge_9/__init__.py b/solutions/challenge_9/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/challenge_9/sum_of_digits.py b/solutions/challenge_9/sum_of_digits.py new file mode 100644 index 000000000..a758eaf37 --- /dev/null +++ b/solutions/challenge_9/sum_of_digits.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for calculating the sum of the digits of a positive integer. + +Module contents: + sum_of_digits: calculates the sum of the digits of a positive integer. + +Created on January 3rd, 2025 +@author: Semira Tesfai +""" + + +def sum_of_digits(n: int) -> int: + """Calculate the sum of the digits of a positive integer. + + Parameters + ---------- + n : int + The non-negative integer whose digits will be summed. + + Returns + ------- + int + The sum of the digits of the given integer. + + Raises + ------ + ValueError + If the argument is not a non-negative integer. + + Examples + -------- + >>> sum_of_digits(123) + 6 + >>> sum_of_digits(4567) + 22 + >>> sum_of_digits(0) + 0 + """ + + if not isinstance(n, int) or n < 0: + raise ValueError("input must be a non-negative integer.") + + return sum(int(digit) for digit in str(n)) diff --git a/solutions/tests/challenge_9/__init__.py b/solutions/tests/challenge_9/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/tests/challenge_9/test_sum_of_digits.py b/solutions/tests/challenge_9/test_sum_of_digits.py new file mode 100644 index 000000000..a509212cf --- /dev/null +++ b/solutions/tests/challenge_9/test_sum_of_digits.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Unit tests for the sum_of_digits function. +Created on January 3rd, 2025 +""" + +import unittest + +from solutions.challenge_9.sum_of_digits import sum_of_digits + + +class TestSumOfDigits(unittest.TestCase): + """Tests for the sum_of_digits function.""" + + def test_with_positive_integer(self): + """Ensure that the sum of digits of a positive integer is calculated correctly.""" + self.assertEqual(sum_of_digits(123), 6) + + def test_with_large_integer(self): + """Ensure that the sum of digits of a large positive integer is calculated correctly.""" + self.assertEqual(sum_of_digits(4567), 22) + + def test_with_zero(self): + """Ensure that the sum of digits of zero is zero.""" + self.assertEqual(sum_of_digits(0), 0) + + def test_with_invalid_input(self): + """Ensure that the function raises an assertion error for invalid inputs.""" + with self.assertRaises(ValueError): + sum_of_digits(-5) + with self.assertRaises(ValueError): + sum_of_digits(4.5) + with self.assertRaises(ValueError): + sum_of_digits("123") + + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_basic_calculator.py b/solutions/tests/test_basic_calculator.py new file mode 100644 index 000000000..752f63ce1 --- /dev/null +++ b/solutions/tests/test_basic_calculator.py @@ -0,0 +1,79 @@ +""" +Test module for basic calculator. + +Test categories: + - Standard cases: addition, subtraction, multiplication, and division + - Edge cases: division by zero, invalid operations + - Defensive tests: ensure proper exceptions are raised for invalid inputs + +Created on 2024-12-29 +Author: Ana Isabel Murillo +""" + +from solutions.basic_calculator.calculate import calculate + +import unittest + + +class TestCalculate(unittest.TestCase): + """Test suite for the calculate function.""" + + def test_addition_positive_numbers(self): + """It should correctly add two positive numbers.""" + self.assertEqual(calculate("add", 5, 3), 8.0) + + def test_addition_negative_numbers(self): + """It should correctly add two negative numbers.""" + self.assertEqual(calculate("add", -5, -3), -8.0) + + def test_addition_zero(self): + """It should correctly add zero to a number.""" + self.assertEqual(calculate("add", 0, 5), 5.0) + + def test_subtraction_positive_numbers(self): + """It should correctly subtract two positive numbers.""" + self.assertEqual(calculate("subtract", 10, 4), 6.0) + + def test_subtraction_negative_numbers(self): + """It should correctly subtract two negative numbers.""" + self.assertEqual(calculate("subtract", -5, -5), 0.0) + + def test_subtraction_zero(self): + """It should correctly subtract a number from zero.""" + self.assertEqual(calculate("subtract", 0, 5), -5.0) + + def test_multiplication_positive_numbers(self): + """It should correctly multiply two positive numbers.""" + self.assertEqual(calculate("multiply", 7, 3), 21.0) + + def test_multiplication_negative_numbers(self): + """It should correctly multiply a negative and a positive number.""" + self.assertEqual(calculate("multiply", -2, 3), -6.0) + + def test_multiplication_with_zero(self): + """It should return zero when multiplying by zero.""" + self.assertEqual(calculate("multiply", 0, 10), 0.0) + + def test_division_positive_numbers(self): + """It should correctly divide two positive numbers.""" + self.assertEqual(calculate("divide", 9, 3), 3.0) + + def test_division_negative_numbers(self): + """It should correctly divide a negative and a positive number.""" + self.assertEqual(calculate("divide", -6, 3), -2.0) + + def test_division_result_with_float(self): + """It should correctly handle division resulting in a float.""" + self.assertAlmostEqual(calculate("divide", 7, 2), 3.5) + + def test_division_by_zero(self): + """It should raise a ValueError when attempting to divide by zero.""" + with self.assertRaises(ValueError) as context: + calculate("divide", 5, 0) + self.assertEqual(str(context.exception), "Cannot divide by zero.") + + def test_invalid_operation(self): + """It should raise a ValueError for an invalid operation.""" + with self.assertRaises(ValueError) as context: + calculate("invalid_op", 5, 3) + self.assertIn("Invalid operation", str(context.exception))