diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 330a04cbc..eb18b4638 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -55,6 +55,8 @@ about: A template PR for code review with a checklist - [ ] The function's name describes it's behavior - [ ] The function's name matches the file name - [ ] The function has correct type annotations +- [ ] The function is not called at the top level of the function file + - _Recursive solutions **can** call the function from **inside** the function body_ ## Strategy @@ -82,5 +84,7 @@ about: A template PR for code review with a checklist - [ ] Variable names are clear and helpful - [ ] The code follows the strategy as simply as possible - [ ] The implementation is as simple as possible given the strategy +- [ ] There are no commented lines of code +- [ ] There are no `print` statements anywhere - [ ] The code includes defensive assertions - [ ] Defensive assertions include as little logic as possible diff --git a/.vscode/settings.json b/.vscode/settings.json index d3ba05557..d226d39db 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -115,7 +115,29 @@ // Enable/disable update table of contents on save "markdown.extension.toc.updateOnSave": false, + "cSpell.words": [ + "Falag", + "Falaq", + "Heba", + "Luyando", + "Muna", + "Raghad", + "Saad", + "Taqwa" + ] +} +======= + "[python]": { + + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "cSpell.words": [ + "catdog", + "cathatbat", + "Falaq", + "Truehello", +======= "editor.defaultFormatter": "charliermarsh.ruff", "editor.formatOnSave": true, "editor.codeActionsOnSave": { @@ -123,8 +145,5 @@ "source.organizeImports.ruff": "explicit" } }, - "cSpell.words": [ - "Falaq", - "Youniss" - ] -} + + diff --git a/README.md b/README.md index 9f8654427..2c8cf2e04 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,86 @@ -# WELCOME TO THE CODE COLLABORATORS' REPOSITORY +# [![Typing SVG](https://readme-typing-svg.herokuapp.com?font=Fira+Code&size=26&pause=1000&width=435&lines=Welcome+to++RepoRangers!+%F0%9F%A4%A0%F0%9F%8C%B2)](https://git.io/typing-svg) -![Visual aid code collaborators are from different parts of the world!](assets/collaboration.jpg) -We are a collaborative group of problem-solvers who are working together to tackle -exciting challenges in this particular project. +![Technology GIF](https://media.giphy.com/media/bGgsc5mWoryfgKBx1u/giphy.gif) + +We are a collaborative group of problem-solvers working together to tackle +exciting Python challenges in this particular project. + +## 🀝 Meet Us + +Here's a fun fact about each of us and our GitHub accounts: + +- **[Agnes](https://github.com/lwjskidsister)** πŸ€“πŸ’Ž + *Fun Fact:* "I'm a nerd when it comes to diamonds." + +- **[Falaq](https://github.com/FalaqMajeed)** βš½πŸ“Š + *Fun Fact:* "Watching and analyzing football matches is my ultimate favorite pastime!" + +- **[Heba](https://github.com/HebaShaheen)** β˜•οΈπŸ˜… + *Fun Fact:* "I drink a lot of Nescafe, 2 or 3 cups a day." + +- **[Luyando](https://github.com/Luyando-Chitindi)** πŸ˜‚πŸ˜‚ + *Fun Fact:* "I absolutely love laughingβ€”it’s my favorite thing to do!" + +- **[Marc](https://github.com/MarcDarazi99)** πŸ‹πŸ˜‹ + *Fun Fact:* "I’m a proud mango loverβ€”if coding were a fruit, it’d be a mango: + sweet, versatile, and endlessly satisfying!" + +- **[Mohammed](https://github.com/Moealfadil)** πŸ€“πŸ“š + *Fun Fact:* "I like mathematical theories." + +- **[Muna](https://github.com/Muna-S)** 🐎❀️ + *Fun Fact:* "I’m completely obsessed with horsesβ€”they're my passion." + +- **[Raghad](https://github.com/raghad598)** πŸ’‡β€β™€οΈ + *Fun Fact:* "Every night before bed, I brush my hair and spritz on some perfume." + +- **[Saad](https://github.com/sashour82)** πŸ‘¨β€πŸ’» + *Fun Fact:* "Failed my first coding course, but graduated with a great GPA and + 12 years in tech!" + +- **[Taqwa](https://github.com/TagwaHashim)** πŸ“šπŸ˜„ + *Fun Fact:* "I'm like a hardcover book full of funny stories." ## πŸš€ Mission -Our main mission is to build a foundation of creativity, collaboration, and learning -while developing basic solutions that help in the build-up of solutions that -provide aid to real-world problems. +Our main mission is to cultivate creativity, collaboration, and continuous +learning, while crafting innovative Python solutions and documenting them +in the best possible way. πŸπŸ“ ## πŸ” Our Current Focus -We are currently exploring the endless world of project challenges. -Each member of this group will select two challenges and share their progress in -this repository. +We are currently exploring the endless world of project challenges. Each member +of this group will select two challenges and share their progress in this +repository. πŸ† -## Repository Overview +## πŸ“‚ Repository Overview This repository contains the following: -- Group collaborations -- Solutions and Tests to individual challenge projects. +- Group collaborations 🀝 +- Solutions and tests for individual challenge projects πŸ”¬ + +## πŸ’‘ Contributions + +Our aim is to promote collaboration among members. We believe there is always room +for improvement in everything we do, and we welcome contributions, suggestions, +and feedback from all members. πŸ› οΈ + +## πŸ“š Want to Know More About Our Collaboration? -## Contributions +- πŸ“ **[Our Group Norms](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/tree/main/collaboration)** +- 🎯 **[Learning Goals](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/blob/main/collaboration/learning_goals.md)** +- πŸ’¬ **[Communication](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/blob/main/collaboration/communication.md)** +- 🚧 **[Constraints](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/blob/main/collaboration/communication.md)** +- πŸ”„ **[Retrospective](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/blob/main/collaboration/retrospective.md)** +- 🐍 **[Our Python challenges and their tests](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-18/tree/main/solutions)** -Our aim is to promote collaboration among members. As we believe that -there is always room for improvement in everything we do, we welcome -contributions, suggestions, and feedback from all members. +## 🌱 What to Expect? -## 🀩 What to expect? +As our project and challenges evolve, so will this README. Stay tuned for our +regular updates! πŸ”„ -As our project and challenges change, so will this README. Stay tuned for our -regular updates, +## πŸ’¬ Remember -Join us as we grow on this platform together! +*Let's keep the hard work flowing, grow together, and put our heart and soul into +every line of code!* πŸ’– diff --git a/collaboration/retrospective.md b/collaboration/retrospective.md index 74e18813b..8b0930e22 100644 --- a/collaboration/retrospective.md +++ b/collaboration/retrospective.md @@ -1,23 +1,75 @@ -# Retrospective +# Retrospective: Group 18 - Collaborative Work Activity ## Stop Doing +- **Inefficient Coordination:** Stop relying on informal communication + methods that cause misunderstandings or delays. + +- **Overloading Tasks:** Avoid taking on excessive responsibilities + without proper delegation or prioritization. + +- **Passive Participation:** Stop being a silent participant in discussions; + ensure to actively contribute to conversations. + ## Continue Doing +- **Effective Teamwork:** Continue fostering collaboration by sharing ideas + openly and respecting diverse perspectives. + +- **Timely Updates:** Maintain a habit of providing timely progress updates + to keep the team aligned. + +- **Using Tools:** Keep leveraging collaborative tools + (e.g., shared documents, project management software) to enhance productivity. + ## Start Doing +- **Structured Planning:** Begin creating more detailed action plans with + clear milestones and deadlines. + +- **Feedback Loops:** Start implementing regular feedback sessions to + evaluate progress and address challenges early. + +- **Skill Development:** Focus on improving specific skills related + to collaborative work and presentation to contribute more effectively. + ## Lessons Learned +- Effective communication is crucial to avoid duplication of efforts and ensure alignment. + +- Clear roles and responsibilities significantly enhance team productivity. + +- Flexibility in strategy allows for better adaptation to unforeseen challenges. + +- Regular check-ins help maintain momentum and ensure accountability. + ______________________________________________________________________ ## Strategy vs. Board ### What parts of your plan went as expected? +- Collaboration tools were effectively utilized to + share resources and coordinate tasks. + +- The team successfully met initial deadlines for project deliverables. + +- Team members demonstrated a willingness to support each other when challenges arose. + ### What parts of your plan did not work out? +- Some tasks were delayed due to unclear task ownership. + +- Miscommunication led to redundant efforts in certain areas. + +- Time zone differences caused occasional scheduling conflicts. + ### Did you need to add things that weren't in your strategy? -### Or remove extra steps? +- Yes, we added weekly synchronization meetings to + address miscommunications and ensure alignment. + +- Included additional training sessions for team members to + improve tool usage efficiency. diff --git a/notes/cheetsheets.md b/notes/cheetsheets.md new file mode 100644 index 000000000..c8037157a --- /dev/null +++ b/notes/cheetsheets.md @@ -0,0 +1,9 @@ +# πŸ“ Cheat Sheets That We Can Use + +## πŸš€ These cheat sheets will cover Python and VS Code + +- πŸ”§ [**VS Code Cheat Sheet**](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf) + β€” Boost your productivity with essential shortcuts. πŸš€ + +- 🐍 [**Python Cheat Sheet**](https://kieranholland.com/best-python-cheat-sheet/) + β€” Quickly reference key Python concepts and syntax. ✏️ diff --git a/notes/creating_linking_issue.md b/notes/creating_linking_issue.md new file mode 100644 index 000000000..b8ffcc4e7 --- /dev/null +++ b/notes/creating_linking_issue.md @@ -0,0 +1,34 @@ +# πŸš€ How to create and link an issue to a pull request + +## πŸ“ How to Create an Issue + +1. Go to the **Issues** tab. πŸ› +2. Click on **New Issue** βž•. +3. Fill out the issue template with all relevant details. πŸ“‹ +4. Assign labels 🏷️ and add it to the project board πŸ“Œ. + +--- + +## πŸ”— Linking an Issue to a Pull Request + +1. Create a branch for your changes. 🌱 +2. Make the necessary edits. ✏️ +3. Open a Pull Request (PR) πŸ› οΈ: + - Use `Fixes #` in the description to close the issue automatically + on merge. βœ… + - For example: + + ```markdown + Fixes #123 + ``` + +--- + +### Link the issue manually if needed + +- Go to the **Linked Issues** section in the PR. +- Search for the issue and add it. πŸ”— + +## πŸ“£ Need Help? + +If you're stuck, don't hesitate to reach out! πŸ†˜ diff --git a/notes/extenstions.md b/notes/extenstions.md new file mode 100644 index 000000000..da68356c7 --- /dev/null +++ b/notes/extenstions.md @@ -0,0 +1,134 @@ +# πŸš€ Guide: Installing and Running Ruff, Black, Pylint, and MarkdownLint in VS Code + +This guide will help you set up and use Ruff, Black, Pylint, and MarkdownLint in +Visual Studio Code (VS Code) to maintain clean and consistent code and Markdown +files and pass all the CI checks. + +--- + +## πŸ› οΈ Prerequisites + +Before starting, ensure the following are installed on your system: + +- [Python](https://www.python.org/) +- [VS Code](https://code.visualstudio.com/) +- [Node.js](https://nodejs.org/) (for MarkdownLint) + +--- + +## πŸ”§ Install Extensions in VS Code + +1. Open VS Code. +2. Go to the Extensions Marketplace (`Ctrl+Shift+X` or `Cmd+Shift+X` on Mac). +3. Install the following extensions: + - **Python** (by Microsoft) + - **MarkdownLint** (by David Anson) + +--- + +## βš™οΈ Setting Up Ruff, Black, and Pylint + +### 1️⃣ Install Ruff + +Ruff is a fast Python linter and formatter. + +```bash +pip install ruff +``` + +To integrate Ruff with VS Code: + +1. Open the VS Code settings (`Ctrl+,` or `Cmd+,` on Mac). +2. Search for `Python β€Ί Linting: Enabled` and ensure it is checked. + +### 2️⃣ Install Black + +Black is a Python code formatter. + +```bash +pip install black +``` + +To use Black in VS Code: + +1. Go to the VS Code settings. +2. Search for `Python β€Ί Formatting: Provider` and set it to `black`. + +### 3️⃣ Install Pylint + +Pylint is a Python linter that checks for errors and enforces a coding standard. + +```bash +pip install pylint +``` + +Enable Pylint in VS Code: + +1. Open the VS Code settings. +2. Search for `Python β€Ί Linting: Pylint Enabled` and ensure it is checked. + +--- + +## πŸ“œ Setting Up MarkdownLint + +MarkdownLint checks for style and consistency issues in Markdown files. + +### Install MarkdownLint + +1. Use npm to install MarkdownLint globally: + + ```bash + npm install -g markdownlint-cli + ``` + +### Run MarkdownLint + +- **From the command line**: + + ```bash + markdownlint yourfile.md + ``` + +- **In VS Code**: + MarkdownLint will automatically highlight issues in your `.md` files as you +edit them. + +--- + +## ▢️ Running the Tools + +### Run Ruff, Black, and Pylint for Python Files + +1. **Ruff**: + + ```bash + ruff path/to/your/code + ``` + +2. **Black**: + + ```bash + black path/to/your/code + ``` + +3. **Pylint**: + + ```bash + pylint path/to/your/code + ``` + +### Run MarkdownLint for Markdown Files + +1. **MarkdownLint**: + + ```bash + markdownlint path/to/your/file.md + ``` + +--- + +## πŸŽ‰ You're All Set + +You are now ready to use Ruff, Black, Pylint, and MarkdownLint in VS Code to +ensure your code and documentation are clean, consistent, and professional. +Happy coding! πŸš€ diff --git a/solutions/count_words.py b/solutions/count_words.py new file mode 100644 index 000000000..c2ef107ca --- /dev/null +++ b/solutions/count_words.py @@ -0,0 +1,35 @@ +""" +A module for counting words in a string. + +Module contents: + - count_words: counts the number of words in a string. + +Created on 01 01 2025 +@author: Raghad +""" + + +def count_words(text: str) -> int: + """Count the number of words in a given string. + + Parameters: + text: str, the input string to analyze + + Returns -> int: number of words in the text + + Raises: + AssertionError: if the argument is not a string + + >>> count_words("Hello World") + 2 + >>> count_words("Python programming is fun") + 4 + >>> count_words("") + 0 + """ + # Validate input + assert isinstance(text, str), "Input must be a string" + + # Split the text by whitespace and count the resulting parts + words = text.split() + return len(words) diff --git a/solutions/cumulative_sum.py b/solutions/cumulative_sum.py index 6cd87f1c1..5c246f54a 100644 --- a/solutions/cumulative_sum.py +++ b/solutions/cumulative_sum.py @@ -13,7 +13,7 @@ - cumulative_sum(numbers: list) -> list: Computes and returns a list of cumulative sums from the input list. -Author: Falaq Youniss +Author: Falaq Youniss. Date: 29/12/2024 """ diff --git a/solutions/decimal_to_binary.py b/solutions/decimal_to_binary.py new file mode 100644 index 000000000..ba2f9e08e --- /dev/null +++ b/solutions/decimal_to_binary.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A function to convert decimal numbers to binary. + +Created on 1/1/2025 +@author: Heba Shaheen +""" + + +def decimal_to_binary(decimal_input: int) -> str: + """Give the binary number for a decimal + + Args: + decimal_input (int): Decimal number to be converted + + Returns: + str: Binary representation of the decimal number + + Raises: + AssertionError: if the input is not an integer + + >>> decimal_to_binary(10) + "1010" + + >>> decimal_to_binary(20) + "10100" + + >>> decimal_to_binary(255) + "11111111" + """ + # Handle the edge case for 0 + assert isinstance(decimal_input, int), "The input should be integer" + assert decimal_input >= 0, "Give a positive input" + if decimal_input == 0: + return "0" + binary = "" + while decimal_input > 0: + binary = str(decimal_input % 2) + binary + decimal_input //= 2 + return binary diff --git a/solutions/is_palindrome.py b/solutions/is_palindrome.py new file mode 100644 index 000000000..61ee8e2de --- /dev/null +++ b/solutions/is_palindrome.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for checking if a given string is a palindrome (reads the same backward as forward) + +Module contents: + - palindrome: input string is palindrome if it reads the same backward as forward + +Created on 30.12.2024 +@author: Saad M. Ashour +""" + + +def is_palindrome(input_string: str) -> bool: + """ + Check if a given string is a palindrome. + + A palindrome is a word, phrase, number, or other sequence of characters + that reads the same forward and backward, ignoring spaces, punctuation, + and case sensitivity. + + Parameters: + input_string (str): The input string to be checked. + + Returns: + bool: True if the input string is a palindrome, False otherwise. + + Examples: + >>> is_palindrome("A man, a plan, a canal, Panama") + True + >>> is_palindrome("hello") + False + >>> is_palindrome("Madam") + True + """ + # AssertionError: Input must be a string + assert isinstance(input_string, str), "Input must be a string" + + # Remove non-alphanumeric characters and convert to lowercase + cleaned = "".join(char.lower() for char in input_string if char.isalnum()) + + # Check if the cleaned string is equal to its reverse + return cleaned == cleaned[::-1] diff --git a/solutions/list_to_string.py b/solutions/list_to_string.py new file mode 100644 index 000000000..44c8e7f63 --- /dev/null +++ b/solutions/list_to_string.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Module: List to String Converter + +Description: + This module provides a function to convert a list of elements (integers, floats, + strings, booleans) into a single concatenated string. It handles various data + types and ensures that all elements are appropriately converted to strings and joined together. + +Module Contents: + - list_to_string(lst: list) -> str: + Converts a list of elements into a single concatenated string. + Ensures proper handling of different data types and raises appropriate errors + for invalid inputs. + +Author: Falaq Youniss +Date: 30/12/2024 +""" + + +def list_to_string(lst: list) -> str: + """ + Converts a list of elements into a single concatenated string. + + Args: + lst (list): A list of items which can include integers, floats, strings, + or booleans. + + Returns: + str: A string that combines all elements of the list. + + Raises: + AssertionError: + - If the input is not a list. + - If the input is `None`. + - If the list is empty. + + >>> list_to_string([1, -4, 3.14]) + '1-43.14' + + >>> list_to_string([True, 'hello']) + 'Truehello' + + >>> list_to_string(['cat', 'hat', 'bat']) + 'cathatbat' + """ + # Validate Input + assert isinstance(lst, list), "Input must be a list." + assert lst is not None, "The input cannot be None." + assert len(lst) > 0, "The list cannot be empty." + + # Initialize an empty result string + result = "" + + # Iterate through the list and convert each element to a string + for element in lst: + result += str(element) # Convert each element to string and concatenate + + return result diff --git a/solutions/max_in.py b/solutions/max_in.py new file mode 100644 index 000000000..ebeebd880 --- /dev/null +++ b/solutions/max_in.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for finding the maximum number of a list of numbers. + +@author: Tagwa Hashim +""" + + +def max_in(numbers): + """ + Finds the maximum number in a list of numbers + + Args: + numbers: A list of numbers (integers or floats). + + Returns: + The maximum number in the list. + + Raises: + ValueError: If the input is not a list. + ValueError: If the input list is empty. + TypeError: If the list contains non-numeric elements. + + Examples: + >>> max_in([1, 5, 3, 9, 2]) + 9 + >>> max_in([2.5, 1.02, 5.7]) + 5.7 + >>> max_in([10.5, -5.2, 8]) + 10.5 + >>> max_in([1, -5, -3]) + 1 + >>> max_in([]) + Traceback (most recent call last): + ValueError: List cannot be empty. + >>> max_in("not a list") + Traceback (most recent call last): + ValueError: Input must be a list. + >>> max_in([1, 2, "three"]) + Traceback (most recent call last): + TypeError: List contains non-numeric elements. + """ + if not isinstance(numbers, list): + raise ValueError("Input must be a list.") + if not numbers: + raise ValueError("List cannot be empty.") + for num in numbers: + if not isinstance(num, (int, float)): # Check if any element is not numeric + raise TypeError("List contains non-numeric elements.") + + max_num = numbers[0] # Initialize max_num with the first element + + for num in numbers[1:]: # Iterate through the list starting from the second element + if num > max_num: + max_num = num + + return max_num diff --git a/solutions/remove_duplicates.py b/solutions/remove_duplicates.py new file mode 100644 index 000000000..8f3d46346 --- /dev/null +++ b/solutions/remove_duplicates.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A Function for removing the duplicates items in a list. + +Created on 2024-12-30 +Author: Heba Shaheen +""" + + +def remove_duplicates(nums: list) -> list: + """ + Given a list, return a new list without any repeated values. + The function goes item by item; if an item is not in the result list, + it appends it; otherwise, it skips it. + + Args: + nums (list): The list from which duplicates will be removed. + + Returns: + list: A list without duplicates. + Raises: + AssertionError: If the input not a list. + + >>> remove_duplicates([2, 4, 2, 5, 5, 7, 2, 6]) + [2, 4, 5, 7, 6] + + >>> remove_duplicates(["a", "v", "e", "e", "q", "v", "q", "a"]) + ['a', 'v', 'e', 'q'] + + >>> remove_duplicates(["Heba", "Noor", "Heba", "Noor"]) + ['Heba', 'Noor'] + """ + assert isinstance(nums, list), "The input should be a list" + result = [] # List to store the result without duplicates. + + for num in nums: + if num not in result: + result.append(num) # Add the number to the result list. + return result diff --git a/solutions/tests/test_count_words b/solutions/tests/test_count_words new file mode 100644 index 000000000..1429ea00c --- /dev/null +++ b/solutions/tests/test_count_words @@ -0,0 +1,42 @@ +""" +A module for testing count_words.py + +Module contents: + - Unit Test cases for function count_words + +Created on 01 01 2025 +@author: Raghad +""" + +import unittest +from solutions.count_words import count_words + + +class TestCountWords(unittest.TestCase): + def test_empty_string(self): + """Test with an empty string""" + self.assertEqual(count_words(""), 0) + + def test_single_word(self): + """Test with a single word""" + self.assertEqual(count_words("hello"), 1) + + def test_multiple_words(self): + """Test with multiple words""" + self.assertEqual(count_words("Hello, world!"), 2) + + def test_extra_spaces(self): + """Test with extra spaces""" + self.assertEqual(count_words(" Hello world "), 2) + + def test_numbers_and_words(self): + """Test with a mix of numbers and words""" + self.assertEqual(count_words("123 hello 456 world"), 4) + + def test_special_characters(self): + """Test with special characters""" + self.assertEqual(count_words("!@# $%^ &*()"), 3) + + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_decimal_to_binary.py b/solutions/tests/test_decimal_to_binary.py new file mode 100644 index 000000000..a2635e9b6 --- /dev/null +++ b/solutions/tests/test_decimal_to_binary.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Unit tests for decimal_to_binary function. + +@author: Heba Shaheen +""" + +import unittest + +from ..decimal_to_binary import decimal_to_binary + + +class TestDecimalToBinary(unittest.TestCase): + """Unit tests for decimal_to_binary function.""" + + def test_number_0(self): + """It should return "0" as binary""" + actual = decimal_to_binary(0) + expected = "0" + self.assertEqual(actual, expected) + + def test_number_2(self): + """It should return "10" as binary""" + actual = decimal_to_binary(2) + expected = "10" + self.assertEqual(actual, expected) + + def test_number_5(self): + """It should return "101" as binary""" + actual = decimal_to_binary(5) + expected = "101" + self.assertEqual(actual, expected) + + def test_number_15(self): + """It should return "1111" as binary""" + actual = decimal_to_binary(15) + expected = "1111" + self.assertEqual(actual, expected) + + def test_non_integer_input(self): + """It should raise an assertion error if the argument is not an integer""" + with self.assertRaises(AssertionError): + decimal_to_binary("1") + + def test_negative_input(self): + """It should raise an assertion error if the argument is negative""" + with self.assertRaises(AssertionError): + decimal_to_binary(-3) diff --git a/solutions/tests/test_is_palindrome.py b/solutions/tests/test_is_palindrome.py new file mode 100644 index 000000000..1f1c8d4b8 --- /dev/null +++ b/solutions/tests/test_is_palindrome.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Unit tests for is_palindrome function. + +@author: Saad M. Ashour +""" + +import unittest + +from ..is_palindrome import is_palindrome + + +class TestIsPalindrome(unittest.TestCase): + """ + Unit tests for the is_palindrome function. + + These tests check various cases to ensure that the is_palindrome function correctly + identifies palindromes, considering case insensitivity, non-alphanumeric characters, + and other edge cases. + """ + + def test_palindrome(self): + """ + Test cases where the string is a palindrome. + """ + actual = is_palindrome("A man, a plan, a canal, Panama") + self.assertTrue(actual) + + def test_non_palindrome(self): + """ + Test cases where the string is not a palindrome. + """ + actual = is_palindrome("hello") + self.assertFalse(actual) + + def test_empty_string(self): + """ + Test case where the input is an empty string, which is considered a palindrome. + """ + actual = is_palindrome("") + self.assertTrue(actual) + + def test_single_character(self): + """ + Test case where the input is a single character, which is always a palindrome. + """ + actual = is_palindrome("a") + self.assertTrue(actual) + + def test_only_non_alphanumeric(self): + """ + Test case where the input contains only non-alphanumeric characters. + The function should ignore them and return True for empty string. + """ + actual = is_palindrome("!@#$$@!") + self.assertTrue(actual) + + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_list_to_string.py b/solutions/tests/test_list_to_string.py new file mode 100644 index 000000000..db3769c62 --- /dev/null +++ b/solutions/tests/test_list_to_string.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Module: test_list_to_string + +Description: + This module contains test cases for the `list_to_string` function defined + in the `list_to_string_converter.py` module. It tests the function's behavior + with various input scenarios, ensuring that it handles different edge cases and + returns the expected concatenated string. + +Test Categories: + - Standard cases: List of integers, floats, strings, and booleans. + - Edge cases: single-element list, list with mixed data types. + - Defensive tests: None input, Non-list inputs, Empty list. + +Author: Falaq Youniss +Date: 30/12/2024 +""" + +import unittest +from ..list_to_string import list_to_string + + +class TestListToString(unittest.TestCase): + """Test cases for the `list_to_string` function.""" + + # Standard test cases + def test_integers(self): + """It should return a concatenated string of integers.""" + self.assertEqual(list_to_string([1, 2, 3]), "123") + + def test_floats(self): + """It should return a concatenated string of floats.""" + self.assertEqual(list_to_string([1.1, 2.2, 3.3]), "1.12.23.3") + + def test_strings(self): + """It should return a concatenated string of strings.""" + self.assertEqual(list_to_string(["cat", "hat", "bat"]), "cathatbat") + + def test_booleans(self): + """It should return a concatenated string of booleans.""" + self.assertEqual(list_to_string([True, False]), "TrueFalse") + + # Edge cases + def test_mixed_types(self): + """It should return a concatenated string of mixed types.""" + self.assertEqual(list_to_string([1, "cat", 3.5, True]), "1cat3.5True") + + def test_single_element(self): + """It should return the same single element as a string.""" + self.assertEqual(list_to_string([42]), "42") + + def test_repeated_element(self): + """It should return repeated elements""" + self.assertEqual(list_to_string([1, 1, 1, 1]), "1111") + + def test_empty_element(self): + """It should ignore empty elements""" + self.assertEqual(list_to_string(["cat", "", "dog", ""]), "catdog") + + def test_space_element(self): + """It should return elements with space elements""" + self.assertEqual(list_to_string(["cat", " ", "dog", " "]), "cat dog ") + + # Defensive tests + def test_none_input(self): + """It should raise an AssertionError for None input.""" + with self.assertRaises(AssertionError): + list_to_string(None) + + def test_non_list_input(self): + """It should raise an AssertionError for non-list input.""" + with self.assertRaises(AssertionError): + list_to_string("not a list") + + def test_empty_list(self): + """It should raise an AssertionError for empty list.""" + with self.assertRaises(AssertionError): + list_to_string([]) + + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_max_in.py b/solutions/tests/test_max_in.py new file mode 100644 index 000000000..7f0229688 --- /dev/null +++ b/solutions/tests/test_max_in.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Module: test_max_in + +Description: + This module contains unit tests for the 'max_in' function defined + in the 'max_in.py' module. + +Author: Tagwa Hashim + +""" + +import unittest +from ..max_in import max_in + + +class TestMaxIn(unittest.TestCase): + """Test the max_in function""" + + def test_positive_integers(self): + """it should return 9 as the maximum number in this list""" + + self.assertEqual(max_in([1, 5, 3, 9, 2]), 9) + + def test_positive_floats(self): + """it should return 10.5 as the maximum number in this list""" + self.assertEqual(max_in([10.5, 5.2, 8.7]), 10.5) + + def test_mix_types(self): + """it should return 1 as the maximum number in this list""" + self.assertEqual(max_in([1, -5.5, -3]), 1) + + def test_empty_list(self): + """It should raise AssertionError for empty list.""" + with self.assertRaises(ValueError): + self.assertEqual(max_in([]), "List cannot be empty.") + + def test_single_element_list(self): + """It should return the single element.""" + self.assertEqual(max_in([5]), 5) + + def test_non_list_input(self): + """It should raise AssertionError for non list input.""" + with self.assertRaises(ValueError): + self.assertEqual(max_in("not a list"), "Input must be a list.") + + def test_non_numeric_list(self): + """It should raise AssertionError for non-numeric list elements.""" + with self.assertRaises(TypeError): + self.assertEqual( + max_in([1, 2, "three"]), "List contains non-numeric elements." + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/solutions/tests/test_remove_duplicates.py b/solutions/tests/test_remove_duplicates.py new file mode 100644 index 000000000..9416ab8b2 --- /dev/null +++ b/solutions/tests/test_remove_duplicates.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Test module for remove_duplicates function + +Created on 2024-12-30 +Author: Heba Shaheen +""" + +import unittest + +from ..remove_duplicates import remove_duplicates + + +class TestRemoveDuplicates(unittest.TestCase): + """Test remove_duplicates function""" + + # Standard test cases + def test_numbers_list(self): + """It should remove duplicates numbers. give [1, 2, 3, 4]""" + self.assertEqual(remove_duplicates([1, 2, 3, 2, 3, 4]), [1, 2, 3, 4]) + + def test_letters_list(self): + """It should remove duplicates letters. give ["a", "v", "e", "q"]""" + self.assertEqual( + remove_duplicates(["a", "v", "e", "e", "q"]), ["a", "v", "e", "q"] + ) + + def test_mix_list(self): + """It should remove duplicates items. give [1, 2, 3, "e", 5, "a"]""" + self.assertEqual( + remove_duplicates([1, 2, 3, "e", 2, 1, "e", 5, "a"]), [1, 2, 3, "e", 5, "a"] + ) + + # Edge cases + def test_empty_list(self): + """It should return empty list""" + self.assertEqual(remove_duplicates([]), []) + + # Defensive tests + def test_invalid_type(self): + """It should raise AssertionError if numbers is not a list""" + with self.assertRaises(AssertionError): + remove_duplicates("1, 2, 2") + + +if __name__ == "__main__": + unittest.main()