diff --git a/solutions/README.md b/solutions/README.md index 9852346d2..800b37986 100644 --- a/solutions/README.md +++ b/solutions/README.md @@ -1 +1,150 @@ # Solutions + +## This file contains a brief on the challenges completed by Group 18 Team + +### factorial + +- **description:** A module for Computing the factorial of + a non-negative integer n. + +- **written by:** Saad (sashour82) + +- **reviewed by:** Luyandochitindi (Luyando-Chitindi) + +### is_palinrome + +- **description:** A module for checking if a given string is + a palindrome (reads the same backward as forward). + +- **written by:** Saad (sashour82) + +- **reviewed by:** Falaq (FalaqMajeed) + +### is_even + +- **description:** A module that contains a function that checks if a number is even. + +- **written by:** Luyandochitindi (Luyando-Chitindi) + +- **reviewed by:** Mohammed (Moealfadil) + +### is_positive + +- **description:** A module that contains a function that checks if a number is positive. + +- **written by:** Luyandochitindi (Luyando-Chitindi) + +- **reviewed by:**Β Muna (Muna-S) + +### mean + +- **description:** Calculates the mean of numbers in a list + +- **written by:** Mohammed (Moealfadil) + +- **reviewed by:** Falaq (FalaqMajeed) + +### is_prime + +- **description:** Checks if a number is prime or not + +- **written by:** Mohammed (Moealfadil) + +- **reviewed by:** Luyandochitindi (Luyando-Chitindi) + +### cumulative_sum + +- **description:** Calculates the cumulative sum of a list by iterating + through its elements and maintaining a running total + +- **written by:** Falaq (FalaqMajeed) + +- **reviewed by:** Mohammed (Moealfadil) + +### list_to_string + +- **description:** Converts a list into a single string + +- **written by:** Falaq (FalaqMajeed) + +- **reviewed by:** Raghad (raghad598) + +### max_in + +- **description:** Find the maximum number in a list + +- **written by:** TagwaHashim (TagwaHashim) + +- **reviewed by:** Raghad (raghad598) + +### sum_of + +- **description:** Calculate the summation of two numbers + +- **written by:** TagwaHashim (TagwaHashim) + +- **reviewed by:** Muna (Muna-S) + +### binary_to_decimal + +- **description:** Give the decimal number for a binary + +- **written by:** Muna (Muna-S) + +- **reviewed by:** TagwaHashim (TagwaHashim), Falaq (FalaqMajeed), Saad (sashour82) + +### leap_year + +- **description:** Checks whether a year is a leap year + +- **written by:** Muna (Muna-S) + +- **reviewed by:** TagwaHashim (TagwaHashim) + +### remove_duplicates + +- **description:** Take a list and return it without any repeated values + +- **written by:** Heba (HebaShaheen) + +- **reviewed by:** Saad (sashour82) + +### binary_decimal_conversion + +- **description:** Gives the binary number for a decimal and vice versa + +- **written by:** Heba (HebaShaheen) + +- **reviewed by:** Saad (sashour82) + +### count_words + +- **description:** Counts the number of words in a string + +- **written by:** Raghad (raghad598) + +- **reviewed by:** Saad (sashour82) + +### area_of_circle + +- **description:** Calculates the area of a circle given its radius + +- **written by:** Raghad (raghad598) + +- **reviewed by:** Heba (HebaShaheen), Mohammed (Moealfadil) + +### hex_to_binary + +- **description:** Converts a hexadecimal string to its binary equivalent + +- **written by:** Marc (MarcDarazi99) + +- **reviewed by:** Mohammed (Moealfadil) + +### binary_to_hex + +- **description:** Converts a binary string to its hexadecimal equivalent + +- **written by:** Marc (MarcDarazi99) + +- **reviewed by:** Mohammed (Moealfadil), Heba (HebaShaheen), Falaq (FalaqMajeed) diff --git a/solutions/area_of_circle.py b/solutions/area_of_circle.py new file mode 100644 index 000000000..c3562cfca --- /dev/null +++ b/solutions/area_of_circle.py @@ -0,0 +1,47 @@ +""" +A module for calculating the area of a circle. + +Module contents: + - area_of_circle: calculates the area of a circle given its radius. + +Created on 01 04 2025 +@author: Raghad +""" + +import math + + +# Define a function to calculate the area of a circle. +def area_of_circle(radius: float) -> float: + """Calculate the area of a circle given its radius. + + Parameters: + radius: float, the radius of the circle + + Returns -> float: area of the circle + + Raises: + ValueError: if the radius is negative + + Examples: + >>> area_of_circle(5) + 78.53981633974483 + >>> area_of_circle(0) + 0.0 + >>> area_of_circle(3.5) + 38.48451000647496 + """ + # Raise an error if the radius is negative. + if radius < 0: + raise ValueError("Radius cannot be negative") + + # Calculate and return the area using the formula: area = Ο€ * r^2 + return math.pi * radius**2 + + +# Entry point for script execution +if __name__ == "__main__": + # Example usage: Calculate the area of a circle with a radius of 5. + radius = 5 + area = area_of_circle(radius) + print("Area of the circle:", area) diff --git a/solutions/binary_to_hex.py b/solutions/binary_to_hex.py new file mode 100644 index 000000000..41adeb156 --- /dev/null +++ b/solutions/binary_to_hex.py @@ -0,0 +1,42 @@ +""" +Module: Binary to Hexadecimal Converter + +This module provides a utility function to convert binary strings to their +corresponding hexadecimal representations. It validates the input to ensure +that it contains only binary digits (0s and 1s) and performs the conversion +accurately. + +@author: Marc Darazi +""" + + +def binary_to_hex(binary_str): + """ + Convert a binary string to its hexadecimal representation. + + Parameters: + binary_str (str): A string of 0s and 1s representing a binary number. + + Returns: + str: The hexadecimal representation of the binary number. + + Raises: + ValueError: If the input is not a valid binary string. + + Example: + >>> binary_to_hex("1101") + 'D' + >>> binary_to_hex("11110000") + 'F0' + >>> binary_to_hex("101010101010") + 'AAA' + """ + # Validate input + if not all(char in "01" for char in binary_str): + raise ValueError("Input must be a binary string containing only 0s and 1s.") + + # Convert binary string to integer + decimal_value = int(binary_str, 2) + + # Convert integer to hexadecimal string and return + return hex(decimal_value)[2:].upper() diff --git a/solutions/hex_to_binary.py b/solutions/hex_to_binary.py new file mode 100644 index 000000000..fcaaeee4b --- /dev/null +++ b/solutions/hex_to_binary.py @@ -0,0 +1,44 @@ +""" +This module provides a utility function to convert a hexadecimal string +to its binary representation. + +Functions: +- hex_to_binary: Converts a hexadecimal string to its binary equivalent. + +Author: Marc Darazi +""" + + +def hex_to_binary(hex_string): + """ + Convert a hexadecimal string to its binary representation. + + Parameters: + hex_string (str): A string representing a hexadecimal number. + It can include a leading '0x' prefix or not. + + Returns: + str: A binary string representation of the given hexadecimal number, + with leading zeros preserved. + + Raises: + ValueError: If the input string is not a valid hexadecimal number. + + Example: + >>> hex_to_binary("1A") + '11010' + >>> hex_to_binary("0xFF") + '11111111' + >>> hex_to_binary("0x0") + '0' + """ + # Remove '0x' prefix if present + if hex_string.startswith("0x"): + hex_string = hex_string[2:] + + try: + # Convert to integer, then to binary + binary_string = bin(int(hex_string, 16))[2:] # Remove '0b' prefix + return binary_string + except ValueError: + raise ValueError("Invalid hexadecimal string") diff --git a/solutions/IsPrime.py b/solutions/is_prime.py similarity index 70% rename from solutions/IsPrime.py rename to solutions/is_prime.py index 3e00390d8..ddb48720f 100644 --- a/solutions/IsPrime.py +++ b/solutions/is_prime.py @@ -1,36 +1,36 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -A module for finding if an integer is prime. +Module for finding if an integer is prime. Module contents: - - IsPrime: finds if an integer is prime. + - is_prime: finds if an integer is prime. Created on XX XX XX @author: Mohammed Elfadil """ -def IsPrime(a: int) -> str: +def is_prime(a: int) -> str: """Checks if an integer is prime. Parameter: a: int Return -> str: whether a is prime or not Raises: AssertionError: if the argument is not an integer - >>> IsPrime(0) + >>> is_prime(0) not prime - >>> IsPrime(1) + >>> is_prime(1) not prime - >>> IsPrime(2) + >>> is_prime(2) prime - >>> IsPrime(4) + >>> is_prime(4) not prime - >>> IsPrime(7) + >>> is_prime(7) prime - >>> IsPrime(2.5) + >>> is_prime(2.5) invalid input - >>> IsPrime(-1) + >>> is_prime(-1) not prime """ if not isinstance(a, int): diff --git a/solutions/leap_year.py b/solutions/leap_year.py new file mode 100644 index 000000000..87000846f --- /dev/null +++ b/solutions/leap_year.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +The module checks whether a given year is a leap year. +create by Muna Sattouf on January 9, 2025 +Completed on January 10, 2024 + +A year is a leap year if it is divisible by 4, +and if it is divisible by 100, it must also be divisible by 400. +""" + + +def leap_year(year: int) -> bool: + """ + Checks whether the given year is a leap year. + + Argument: + year, a positive integer + + Returns: + boolean: True if the year is a leap year, false otherwise. + + Examples: + >>> leap_year(2024) + True + >>> leap_year(1900) + False + >>> leap_year(2021) + False + """ + if not isinstance(year, int): + raise ValueError("Year must be an integer") + if year < 0: + raise ValueError("Year must be positive integer") + + return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) diff --git a/solutions/sum_of.py b/solutions/sum_of.py new file mode 100644 index 000000000..42694ab68 --- /dev/null +++ b/solutions/sum_of.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on XX XX XX + +A module gives a summation of two numbers. + +@author: Tagwa Hashim +""" + + +def sum_of(num1, num2): + """ + Adds two numbers and returns their sum. + + Args: + num1: The first number. Can be an integer or a float. + num2: The second number. Can be an integer or a float. + + Returns: + The sum of num1 and num2. + + Raises: + AssertionError: If either num1 or num2 is not a number (int or float). + + Examples: + >>> sum_of(3, 5) + 8 + >>> sum_of(2.5, 3.7) + 6.2 + >>> sum_of("hello", 2.718) + Traceback (most recent call last): + ... + AssertionError: Both arguments must be numbers (int or float). + """ + assert isinstance(num1, (int, float)) and isinstance(num2, (int, float)), ( + "Both arguments must be numbers (int or float)." + ) + return num1 + num2 diff --git a/solutions/tests/README.md b/solutions/tests/README.md index 007eb9551..3735407a9 100644 --- a/solutions/tests/README.md +++ b/solutions/tests/README.md @@ -1 +1,19 @@ -# Tests +# Test Folder πŸ—‚οΈ + +This folder contains test files designed to validate the functionality of the +functions in the [solutions](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/tree/main/solutions) +folder. βœ… + +## Structure πŸ—οΈ + +- Each test file corresponds to a function in the [solutions](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/tree/main/solutions) +folder. πŸ”— +- Tests are written using Python's `unittest` framework. 🐍 +- Folder structure: `test_file_1.py`, `test_file_2.py`, etc. πŸ“‚ + +## Running Tests ▢️ + +To run all tests in the folder, use the following command: + +```bash +python -m unittest path/to/test/folder diff --git a/solutions/tests/test_area_of_circle.py b/solutions/tests/test_area_of_circle.py new file mode 100644 index 000000000..82d575aae --- /dev/null +++ b/solutions/tests/test_area_of_circle.py @@ -0,0 +1,38 @@ +import unittest +from solutions.area_of_circle import area_of_circle + + +class TestCircleArea(unittest.TestCase): + """Unit tests for the area_of_circle function.""" + + def test_positive_radius(self): + """Test the function with positive radius values.""" + self.assertAlmostEqual(area_of_circle(5), 78.53981633974483) + self.assertAlmostEqual(area_of_circle(10), 314.1592653589793) + + def test_zero_radius(self): + """Test the function with a zero radius.""" + self.assertEqual(area_of_circle(0), 0.0) + + def test_large_radius(self): + """Test the function with a very large radius.""" + self.assertAlmostEqual(area_of_circle(1000), 3141592.653589793) + + def test_negative_radius(self): + """Test the function with a negative radius.""" + with self.assertRaises(ValueError) as context: + area_of_circle(-5) + self.assertEqual(str(context.exception), "Radius cannot be negative") + + def test_invalid_type(self): + """Test the function with an invalid type for radius.""" + with self.assertRaises(TypeError): + area_of_circle("string") + with self.assertRaises(TypeError): + area_of_circle([1, 2, 3]) + with self.assertRaises(TypeError): + area_of_circle(None) + + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_binary_to_hex.py b/solutions/tests/test_binary_to_hex.py new file mode 100644 index 000000000..79f0f011d --- /dev/null +++ b/solutions/tests/test_binary_to_hex.py @@ -0,0 +1,49 @@ +""" +Module: Binary to Hexadecimal Converter + +This module provides a utility function to convert binary strings to their +corresponding hexadecimal representations. It validates the input to ensure +that it contains only binary digits (0s and 1s) and performs the conversion +accurately. + +Author: Marc Darazi +""" + +import unittest +from solutions.binary_to_hex import binary_to_hex + + +class TestBinaryToHex(unittest.TestCase): + # Unit Tests + def test_binary_to_hex_valid(self): + """ + Test binary_to_hex with valid binary input. + Asserts the correct hexadecimal output is produced. + """ + assert binary_to_hex("1101") == "D" + + def test_binary_to_hex_large(self): + """ + Test binary_to_hex with a larger binary input. + Asserts the correct hexadecimal output is produced. + """ + assert binary_to_hex("11110000") == "F0" + + def test_binary_to_hex_minimum(self): + """ + Test binary_to_hex with the smallest valid binary input. + Asserts the correct hexadecimal output is produced. + """ + assert binary_to_hex("0") == "0" + + def test_binary_to_hex_invalid(self): + """ + Test binary_to_hex with invalid input containing non-binary characters. + Asserts that a ValueError is raised. + """ + try: + binary_to_hex("11012") + except ValueError as e: + assert str(e) == "Input must be a binary string containing only 0s and 1s." + else: + assert False, "ValueError was not raised for invalid input." diff --git a/solutions/tests/test_hex_to_binary.py b/solutions/tests/test_hex_to_binary.py new file mode 100644 index 000000000..d6c2c66ab --- /dev/null +++ b/solutions/tests/test_hex_to_binary.py @@ -0,0 +1,60 @@ +""" +This module provides a utility function to convert a hexadecimal string +to its binary representation. + +Functions: +- hex_to_binary: Converts a hexadecimal string to its binary equivalent. + +Author: Marc Darazi +""" + +import unittest +from ..hex_to_binary import hex_to_binary + + +class TestHexToBinary(unittest.TestCase): + """ + Unit tests for the hex_to_binary function. + + These tests validate that the hex_to_binary function correctly converts + hexadecimal strings to binary strings, handling both cases with and + without the '0x' prefix and invalid inputs. + """ + + def test_valid_hex_without_prefix(self): + """ + Test converting a valid hexadecimal string without the '0x' prefix. + """ + self.assertEqual(hex_to_binary("1A"), "11010") + + def test_valid_hex_with_prefix(self): + """ + Test converting a valid hexadecimal string with the '0x' prefix. + """ + self.assertEqual(hex_to_binary("0xFF"), "11111111") + + def test_single_digit_hex(self): + """ + Test converting a single digit hexadecimal string. + """ + self.assertEqual(hex_to_binary("9"), "1001") + + def test_hex_with_lowercase_letters(self): + """ + Test converting a hexadecimal string with lowercase letters. + """ + self.assertEqual(hex_to_binary("a"), "1010") + + def test_invalid_hex_with_non_hex_characters(self): + """ + Test an invalid hexadecimal string with non-hex characters. + """ + with self.assertRaises(ValueError): + hex_to_binary("G1") + + def test_empty_string(self): + """ + Test an empty string as input, which should raise a ValueError. + """ + with self.assertRaises(ValueError): + hex_to_binary("") diff --git a/solutions/tests/test_IsPrime.py b/solutions/tests/test_is_prime.py similarity index 79% rename from solutions/tests/test_IsPrime.py rename to solutions/tests/test_is_prime.py index 399160f98..4364f8a89 100644 --- a/solutions/tests/test_IsPrime.py +++ b/solutions/tests/test_is_prime.py @@ -1,67 +1,67 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- import unittest -from solutions.IsPrime import IsPrime +from solutions.is_prime import is_prime class TestIsPrime(unittest.TestCase): - """test the IsPrime function""" + """test the is_prime function""" def test_0(self): """It should evaluate not prime""" - actual = IsPrime(0) + actual = is_prime(0) expected = "not prime" self.assertEqual(actual, expected) def test_1(self): """It should evaluate not prime""" - actual = IsPrime(1) + actual = is_prime(1) expected = "not prime" self.assertEqual(actual, expected) def test_2(self): - actual = IsPrime(2) + actual = is_prime(2) expected = "prime" self.assertEqual(actual, expected) def test_4(self): """its should evaluate not prime""" - actual = IsPrime(4) + actual = is_prime(4) expected = "not prime" self.assertEqual(actual, expected) def test_7(self): """It should evaluate prime""" - actual = IsPrime(7) + actual = is_prime(7) expected = "prime" self.assertEqual(actual, expected) def test_9(self): """It should evaluate not prime""" - actual = IsPrime(9) + actual = is_prime(9) expected = "not prime" self.assertEqual(actual, expected) def test_11(self): """It should evaluate prime""" - actual = IsPrime(11) + actual = is_prime(11) expected = "prime" self.assertEqual(actual, expected) def test_13(self): """It should evaluate prime""" - actual = IsPrime(13) + actual = is_prime(13) expected = "prime" self.assertEqual(actual, expected) def test_negative(self): """It should evaluate not prime""" - actual = IsPrime(-1) + actual = is_prime(-1) expected = "not prime" self.assertEqual(actual, expected) def test_not_integer(self): """It should evaluate not prime""" - actual = IsPrime(1.5) + actual = is_prime(1.5) expected = "invalid input" self.assertEqual(actual, expected) diff --git a/solutions/tests/test_leap_year.py b/solutions/tests/test_leap_year.py new file mode 100644 index 000000000..a5943e3ca --- /dev/null +++ b/solutions/tests/test_leap_year.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Test for leap_year function. +Created and completed by Muna Sattouf on January 10, 2024. +""" + +import unittest +from solutions.leap_year import leap_year + + +class TestLeapYear(unittest.TestCase): + """ + Test cases for the leap_year function + """ + + def test_divisibility_by_4(self): + """ + Tests a year is divisible by 4 but not 100 + """ + self.assertTrue(leap_year(2024)) + + def test_not_leap_divisible_by_100(self): + """ + Tests a year divisible by 100 but not 400 + """ + self.assertFalse(leap_year(1900)) + + def test_leap_divisible_by_400(self): + """ + Tests a year divisible by 400 + """ + self.assertTrue(leap_year(2000)) + + def test_not_leap_not_divisble_by_4(self): + """ + Tests a year not divisble by 4 + """ + self.assertFalse(leap_year(2023)) + + def test_invalid_type(self): + """ + A ValueError should be raised if type is not integer + """ + with self.assertRaises(ValueError): + leap_year("hi") + + def test_invalid_negative(self): + """ + A value error must be rasied if the year is a negative integer + """ + with self.assertRaises(ValueError): + leap_year(-175) + + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_sum_of.py b/solutions/tests/test_sum_of.py new file mode 100644 index 000000000..c8563b6e3 --- /dev/null +++ b/solutions/tests/test_sum_of.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Unit tests for the sum_of function. + +@author: Tagwa Hashim +""" + +import unittest + +from solutions.sum_of import sum_of + + +class TestSumOf(unittest.TestCase): + """Test the sum_of function""" + + def test_add_integers(self): + """Test sum_of of two integers.""" + self.assertEqual(sum_of(7, 12), 19) + + def test_add_floats(self): + """Test sum_of of two floats.""" + self.assertEqual(sum_of(1.6, 3.3), 4.9) + + def test_add_mixtype(self): + """Test sum_of of integer and float.""" + self.assertEqual(sum_of(3, 2.05), 5.05) + + def test_add_zero(self): + """Test sum_of with zero.""" + self.assertEqual(sum_of(0, 5), 5) + self.assertEqual(sum_of(5, 0), 5) + + def test_add_negative_numbers(self): + """Test sum_of with negative numbers.""" + self.assertEqual(sum_of(-3, -5), -8) + self.assertEqual(sum_of(-3, 5), 2) + + def test_invalid_input_type_num(self): + """Test with invalid input type for num1 or num2, should raise assertion error""" + + with self.assertRaises(AssertionError): + sum_of("hello", 2) + sum_of(18, "hello") + + +if __name__ == "__main__": + unittest.main()