From 5f3e05a4af48f0b100198047a3493db0ffa31e6b Mon Sep 17 00:00:00 2001 From: Alexander Andom <121858703+aandom@users.noreply.github.com> Date: Sun, 29 Dec 2024 14:59:03 +0000 Subject: [PATCH 01/48] learning-goals-readme-done #2 --- collaboration/learning_goals.md | 80 ++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/collaboration/learning_goals.md b/collaboration/learning_goals.md index 11c583d2b..abe8de1a1 100644 --- a/collaboration/learning_goals.md +++ b/collaboration/learning_goals.md @@ -1,5 +1,81 @@ # Learning Goals -## Collective +Our learning goals are categorized into two main areas: Focuses on Collective +Goals, that is improving together as a team and Individual Goals helping +individual areas of growth based on the aspirations of each member. This +structured approach guarantees both group development and individual development -## Individual +## Collective Learning Goals + +Together we seek to build a collaborative development environment where we +sharpen our technical and communication skills. Through practice and continuous +learning, we aim to develop a strong foundation in software development and Python +programming. Below are our key focus areas as a collective: + +1. Collaborative Development Skills + + - Develop effective collaboration practices through GitHub workflows, including: + - **Issues**: Creating, tracking, and assigning tasks. + - **Pull Requests (PRs)**: Submitting, reviewing, and merging pull + requests to ensure code quality. + - **Merging**: Understanding different merge strategies and resolving conflicts. + - **Projects**: Organizing tasks and milestones using GitHub Projects + for visual tracking. + - **Branching**: Managing branches effectively to keep the repository + clean and organized. + - **GitHub CLI**: Managing repositories, pull requests, and issues from + the terminal. + +2. Effective Communication + + - Enhance communication skills within the team through: + - **Slack**: Using Slack for group communication. + - **Regular Meetings**: Actively participating in group meetings and + discussions to ensure alignment on goals and progress. + - **Feedback and Collaboration**: Providing and receiving constructive + feedback in both code reviews and team discussions. + +3. Unit Testing + + - Learn and integrate unit testing in Python using the `unittest` module. + +4. Code Review Process + + - Develop an understanding of an effective code review process, including + giving and receiving constructive feedback to improve code quality. + +5. Efficient Development Practices + + - Focus on becoming more efficient developers by improving workflows, + debugging techniques, and programming skills. + +6. Python Programming + + - Strengthen Python programming skills by: + - Writing efficient and well-documented Python code. + +7. Docstring Documentation + + - Learning the art of writing clear and concise docstrings to document code effectively. + +## Individual Learning Goals + +### *Alexander Andom* + +- *Learn New Data Structures*: Learn and implement new data structures that are +unfamiliar or challenging. +- *Improve Debugging Skills*: Develop strategies for debugging code and +resolving issues more efficiently. +- *Deepen Knowledge of Testing Frameworks*: Learn to use `unittest` in Python +to write solid and detailed unit tests. + +### *Mohamed Saed* + +- Mastering GitHub +- To foster my programming skills +- Improve my debugging skills + +### *Amin Abd Elraheem* + +- To Understand how to plan and execute projects on GitHub. +- Transform Ideas into Programs From 9c71170b74971bf5570014c6ede2b65b267c0130 Mon Sep 17 00:00:00 2001 From: Alexander Andom <121858703+aandom@users.noreply.github.com> Date: Sun, 29 Dec 2024 15:50:52 +0000 Subject: [PATCH 02/48] learning-goals-fix-typo #2 --- collaboration/learning_goals.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collaboration/learning_goals.md b/collaboration/learning_goals.md index abe8de1a1..d911159b4 100644 --- a/collaboration/learning_goals.md +++ b/collaboration/learning_goals.md @@ -69,7 +69,7 @@ resolving issues more efficiently. - *Deepen Knowledge of Testing Frameworks*: Learn to use `unittest` in Python to write solid and detailed unit tests. -### *Mohamed Saed* +### *Mohamed Saeed* - Mastering GitHub - To foster my programming skills From 02bca92f6a5d52d0764ff8e8f6cac0342c7f3d47 Mon Sep 17 00:00:00 2001 From: Tbaosman <99553124+Tbaosman@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:40:36 +0400 Subject: [PATCH 03/48] Completed and refined the constraints file --- collaboration/constraints.md | 72 +++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/collaboration/constraints.md b/collaboration/constraints.md index 24079505c..173d80155 100644 --- a/collaboration/constraints.md +++ b/collaboration/constraints.md @@ -1,34 +1,62 @@ - # Constraints -Some boundaries around our project. +--- + +This file reflects some boundaries and challenges that may face our group and project ## External - +These are constraints coming from the outside and we (as a team) +have no control over, for example: + +- **Project deadlines** + - The project must be completed within 3 weeks, with a clear + deadline for each deliverable. +- **Programming Language: Python** + - Python will be used to build the project. No other languages + or frameworks will be used. +- **Version Control with GitHub:** + - The code related to the project has to be pushed to the GitHub + repository And pull requests should be reviewed before merging. +- **Testing Framework: Unittest** + - For testing purposes, the project will use unittest for Python. + And no other testing libraries or frameworks will be introduced. +- **Documentation Standards:** + - During the project, all code should have clear and concise + documentation (using docstrings). +- **Team Size:** + - A team of 10 members will work on this project. + All members will be expected to collaborate. ## Internal: Involuntary - +These are constraints that come from within our team and we have no +control over but we can work on mitigating them: + +- **Skills level:** + - Team members have different levels of experience and + familiarity with programming, Git&GitHub. + +- **amount of time available to work on the project** + - Due to work or life responsibilities, each team member + has a different amount of time that he can use to work on this project. +- **Communication issues** ## Internal: Voluntary - +These are the types of constraints that we’ve decided on to help scope the project. +They include: + +- coding style & conventions +- Follow the code review checklist for the project repository +- The number of hours you want to spend working +- Agreed to use Slack as the main communication channel +- Agreed to use Google Meet for meetings +- We may share the insights or challenges that we faced during problem-solving + to help others learn and reduce the potential time that may be wasted on debugging +- Meeting Frequency and Duration: + - Group meetings should be held at least once a week for up to 1 hour. That said, + team availability will factor into scheduling and it’s expected that all team + members will participate. +- Agreed on completing any outstanding tasks by **January** the **7th**. From 20272eaf5c2fcc4e9b52db32ddf32a8e3db4117c Mon Sep 17 00:00:00 2001 From: kefahalshaer Date: Tue, 31 Dec 2024 14:50:57 +0200 Subject: [PATCH 04/48] add base readme file --- .vscode/settings.json | 4 +- README.md | 105 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index bbda5188d..252022b48 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -119,8 +119,8 @@ "editor.defaultFormatter": "charliermarsh.ruff", "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.fixAll.ruff": true, - "source.organizeImports.ruff": true + "source.fixAll.ruff": "explicit", + "source.organizeImports.ruff": "explicit" } } } diff --git a/README.md b/README.md index e69de29bb..33aa84163 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,105 @@ +# 👋 Welcome: This is `PyRectifier` Group + +## We made this repository to practice what we learn in the `MIT Foundational Track` + +### The most important points that we are as a team individuals practicing here + +1. To master using GitHub & Git. (msaeed) +2. To foster my programming skills. (msaeed) +3. To learn how to work collaboratively within groups and organizations by + learning and practicing the best practices and approaches. (msaeed) +4. To understand how to plan and execute projects on Github. (Amin) +5. To transform my ideas into programs (Amin) +6. Write unit test files. (Kefah) +7. Practicing Review code. (Kefah) +8. ... (Colleagues: Add what you're thinking about) + +### Learning Goals + + Our learning goals are categorized into two main areas: Focus on `Collective + Goals`, that is improving together as a team, and `Individual Goals`, that + focus on helping individual areas of growth based on the aspirations of each + member. This structured approach guarantees both group development and + personal development. + +### 1. Collective Learning Goals + + Together, we seek to build a collaborative development environment where + we sharpen our technical and communication skills. With practice and + continuous learning, we’ll develop a strong foundation in software + development and Python programming. The following will be our key points + as a collective to learn together. + +#### 1. Collaborative Development Skills + +- Develop effective collaboration practices through GitHub workflows, including: + - **Issues**: Creating, tracking, and assigning tasks. + - **Pull Requests (PRs)**: Submitting, reviewing, and merging pull requests + to ensure code quality. + - **Merging**: Understanding different merge strategies and resolving conflicts. + - **Projects**: Organizing tasks and milestones using GitHub Projects for + visual tracking. + - **Branching**: Managing branches effectively to keep the repository clean + and organized. + - **GitHub CLI**: Managing repositories, pull requests, and issues from the terminal. + +#### 2. Effective Communication + +- Enhance communication skills within the team through: + - **Slack**: Using Slack for group communication. + - **Regular Meetings**: Actively participate in group meetings and + discussions to ensure alignment on goals and progress. + - **Feedback and Collaboration**: Providing and receiving constructive + feedback in both code reviews and team discussions. + +#### 3. Unit Testing + +- Learn and integrate unit testing in Python using the unittest module. + +#### 4. Code Review Process + +- Develop an understanding of an effective code review process, giving and + receiving constructive feedback to improve code quality. + +#### 5. Efficient Development Practices + +- Focus on becoming more efficient developers by improving workflows + debugging techniques, and programming skills. + +#### 6. Python Programming + +- Strengthen Python programming skills by: + - Writing efficient, and well-documented Python code. + +#### 7. Docstring Documentation + +- Learn the art of writing. + +### 2. Individual Learning Goals + +#### **Alexander Andom** + + 1. Learn New Data Structures: + - Learn and implement new data structures that are unfamiliar or challenging. + 2. Improve Debugging Skills: + - Develop strategies for debugging code and resolving issues more efficiently. + 3. Deepen Knowledge of Testing Frameworks: + - Learn to use unittest in Python to write solid and detailed unit tests. + +#### **Mohamed Saed** + +- Mastering GitHub +- To foster my programming skills + +#### **Amin Abd Elraheem** + +- To understand how to plan and execute projects on Github. +- To transform my ideas into programs. + +#### **Kefah Albashityalshaer** + +- Improve my programming skills in Python, especially in writing unit test programs +- Mastering Code Review, making PRs, and the other GitHub teams' tasks. +- Improve team's communication. + +--- For the rest team's members, please add yours in the [doc here](https://docs.google.com/document/d/1A2wzylXGlXTTitTcOhgHJp50BXqLRtqdoCEJ2TlCaM0/edit?tab=t.0) From 158c05b9a801b61ac6bd7655c4a3618efd1f733b Mon Sep 17 00:00:00 2001 From: Tbaosman <99553124+Tbaosman@users.noreply.github.com> Date: Wed, 1 Jan 2025 01:32:26 +0400 Subject: [PATCH 05/48] Done with the challenge'longest substring' and its test file --- solutions/longest_substring.py | 41 ++++++++++ solutions/tests/test_longest_substring.py | 92 +++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 solutions/longest_substring.py create mode 100644 solutions/tests/test_longest_substring.py diff --git a/solutions/longest_substring.py b/solutions/longest_substring.py new file mode 100644 index 000000000..11953686f --- /dev/null +++ b/solutions/longest_substring.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +def longest_substring(s: str) -> str: + """ + Function to find the longest substring without repeating characters. + + Parameters: + s (str): The input string. + + Returns: + str: The longest substring without repeating characters. + + Raises: + assertionError: If the input is not a string + ValueError: If the input string is empty. + + Examples: + + >>> longest_substring("abcabcbb") + 'abc' + >>> longest_substring("bbbbb") + 'b' + >>> longest_substring("pwwekew") + 'wek' + """ + assert isinstance(s, str), "Input must be a string" + if not s: + raise ValueError("Input string cannot be empty") + + longest = "" + for i in range(len(s)): + substring = "" + for j in range(i, len(s)): + if s[j] == " ": + continue + if s[j] in substring: + break + substring += s[j] + if len(substring) > len(longest): + longest = substring + return longest diff --git a/solutions/tests/test_longest_substring.py b/solutions/tests/test_longest_substring.py new file mode 100644 index 000000000..60bf6d38b --- /dev/null +++ b/solutions/tests/test_longest_substring.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Test module for long_substring function. +Contains correct tests to help identify bugs in the implementation. + +Test categories: + - Standard cases: typical string inputs + - Edge cases: empty strings, equal + - Defensive tests: invalid inputs + +Created on 2025-1-1 +Author: Mohamed Saeed +""" + +import unittest + +from ..longest_substring import longest_substring + + +class TestFindLongest(unittest.TestCase): + """ + Test class for the longest_substring function. + """ + + def test_standard_case(self): + """ + Test the function with standard inputs. + """ + self.assertEqual(longest_substring("abcabcbb"), "abc") + + def test_single_character(self): + """ + Test the function with a single character. + """ + self.assertEqual(longest_substring("a"), "a") + + def test_same_characters(self): + """ + Test the function with a string of the same characters. + """ + self.assertEqual(longest_substring("aaaaa"), "a") + + def test_unique_characters(self): + """ + Test the function with a string of unique characters. + """ + self.assertEqual(longest_substring("qwertyuiop"), "qwertyuiop") + + def test_long_string(self): + """ + Test the function with a long string. + """ + self.assertEqual(longest_substring("mohammedosmanmusasaeed"), "edosman") + + def test_numbers(self): + """ + Test the function with numbers. + """ + self.assertEqual(longest_substring("1234156789"), "234156789") + + def test_numbers_and_characters(self): + """ + Test the function with numbers and characters. + """ + self.assertEqual(longest_substring("1234ab14cd56789"), "ab14cd56789") + + def test_string_with_spaces(self): + """ + Test the function with spaces. + """ + self.assertEqual(longest_substring("a b c d e f g h i"), "abcdefghi") + + def test_empty_case(self): + """ + Test the function with edge inputs. + """ + with self.assertRaises(ValueError): + longest_substring("") + + def test_special_characters(self): + """ + Test the function with special characters. + """ + self.assertEqual(longest_substring("!@#@$%&"), "#@$%&") + + def test_defensive_cases(self): + """ + Test the function with invalid inputs. + """ + with self.assertRaises(AssertionError): + longest_substring(123) From 6ef29224006c9398cb6965aed45d7b523675ec5c Mon Sep 17 00:00:00 2001 From: Tbaosman <99553124+Tbaosman@users.noreply.github.com> Date: Wed, 1 Jan 2025 14:43:05 +0400 Subject: [PATCH 06/48] Added the Module docstring --- solutions/longest_substring.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/solutions/longest_substring.py b/solutions/longest_substring.py index 11953686f..f5973d4b5 100644 --- a/solutions/longest_substring.py +++ b/solutions/longest_substring.py @@ -1,5 +1,17 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +""" +A module for finding the longest substring without repeating characters + +Module contents: + - longest_substring: Function to find the longest substring without repeating characters. + +Created on 2025-1-1 +@author: Mohamed Saeed + +""" + + def longest_substring(s: str) -> str: """ Function to find the longest substring without repeating characters. From 25ab682d14e3b98d4a1873c1c0d8d6aa38e8ce84 Mon Sep 17 00:00:00 2001 From: Alexander Andom <121858703+aandom@users.noreply.github.com> Date: Wed, 1 Jan 2025 11:46:16 +0000 Subject: [PATCH 07/48] is-leap-year-challenge-done --- solutions/is_leap_year.py | 48 +++++++++++++++++++++ solutions/tests/test_is_leap_year.py | 64 ++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 solutions/is_leap_year.py create mode 100644 solutions/tests/test_is_leap_year.py diff --git a/solutions/is_leap_year.py b/solutions/is_leap_year.py new file mode 100644 index 000000000..33aa5001f --- /dev/null +++ b/solutions/is_leap_year.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for determining if a year is a leap year. + +Module contents: + - is_leap_year(year): Determines if a year is a leap year. + +Leap year rules: + - A year is a leap year if it is divisible by 4. + - However, years divisible by 100 are not leap years , unless it is divisible by 400. + +Created on 2025-01-01 +@author: Alexander Andom +""" + + +def is_leap_year(year: int) -> bool: + """Check if a given year is a leap year. + + Parameters: + year : int, The year to check. + + Returns: + bool: True if the year is a leap year, False otherwise. + + Raises: + AssertionError: + - If 'year' is not an integer. + - If 'year' is less than 1583. + + Example: + >>> is_leap_year(2000) + True + + >>> is_leap_year(1900) + False + + >>> is_leap_year(2024) + True + """ + + assert isinstance(year, int), "Year must be an integer" + assert ( + year >= 1583 + ), "Year must be greater than or equal to 1583 (1582 is start of Gregorian Calendar)" + + return (year % 4 == 0) and (year % 100 != 0 or year % 400 == 0) diff --git a/solutions/tests/test_is_leap_year.py b/solutions/tests/test_is_leap_year.py new file mode 100644 index 000000000..92b098d13 --- /dev/null +++ b/solutions/tests/test_is_leap_year.py @@ -0,0 +1,64 @@ + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for testing the is_leap_year function. + +Test cases include: + - Valid leap years (e.g., divisible by 4 but not 100, or divisible by 400). + - Non-leap years (e.g., not divisible by 4, or divisible by 100 but not 400). + - Years outside the Gregorian calendar (e.g., before 1583). + - Invalid inputs (e.g., non-integer values). + +Created on 2025-01-01 +@author: Alexander Andom +""" + + +import unittest +from ..is_leap_year import is_leap_year + +class TestIsLeapYear(unittest.TestCase): + """Test the is_leap_year function""" + + def test_leap_year_2000(self): + """Test for a leap year: 2000""" + self.assertTrue(is_leap_year(2000)) + + def test_non_leap_year_1900(self): + """Test for a non-leap year: 1900""" + self.assertFalse(is_leap_year(1900)) + + def test_leap_year_2024(self): + """Test for a leap year: 2024""" + self.assertTrue(is_leap_year(2024)) + + def test_non_leap_year_2023(self): + """Test for a non-leap year: 2023""" + self.assertFalse(is_leap_year(2023)) + + def test_leap_year_2400(self): + """Test for a leap year: 2400""" + self.assertTrue(is_leap_year(2400)) + + def test_non_leap_year_2100(self): + """Test for a non-leap year: 2100""" + self.assertFalse(is_leap_year(2100)) + + def test_invalid_input_string(self): + """Test for invalid input: string""" + with self.assertRaises(AssertionError): + is_leap_year("two thousand") + + def test_invalid_input_float(self): + """Test for invalid input: float""" + with self.assertRaises(AssertionError): + is_leap_year(2000.5) + + def test_year_below_1583(self): + """Test for a year below 1583 to raise AssertionError""" + with self.assertRaises(AssertionError): + is_leap_year(1500) + +if __name__ == "__main__": + unittest.main() From 532cabed36938f669ed70909afdebd946913e6eb Mon Sep 17 00:00:00 2001 From: Alexander Andom <121858703+aandom@users.noreply.github.com> Date: Wed, 1 Jan 2025 11:50:44 +0000 Subject: [PATCH 08/48] is-leap-year-chal-fix-format --- solutions/tests/test_is_leap_year.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/solutions/tests/test_is_leap_year.py b/solutions/tests/test_is_leap_year.py index 92b098d13..cc92d465d 100644 --- a/solutions/tests/test_is_leap_year.py +++ b/solutions/tests/test_is_leap_year.py @@ -1,4 +1,3 @@ - #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @@ -14,10 +13,11 @@ @author: Alexander Andom """ - import unittest + from ..is_leap_year import is_leap_year + class TestIsLeapYear(unittest.TestCase): """Test the is_leap_year function""" @@ -60,5 +60,6 @@ def test_year_below_1583(self): with self.assertRaises(AssertionError): is_leap_year(1500) + if __name__ == "__main__": unittest.main() From c1d2b86aa76903fe4ac97dea10718e84e64814d4 Mon Sep 17 00:00:00 2001 From: Alexander Andom <121858703+aandom@users.noreply.github.com> Date: Wed, 1 Jan 2025 11:57:31 +0000 Subject: [PATCH 09/48] is-leap-year-ch-done #16 --- solutions/is_leap_year.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solutions/is_leap_year.py b/solutions/is_leap_year.py index 33aa5001f..50dfc5cd9 100644 --- a/solutions/is_leap_year.py +++ b/solutions/is_leap_year.py @@ -40,9 +40,9 @@ def is_leap_year(year: int) -> bool: True """ - assert isinstance(year, int), "Year must be an integer" + assert isinstance(year, int), "year must be an integer" assert ( year >= 1583 - ), "Year must be greater than or equal to 1583 (1582 is start of Gregorian Calendar)" + ), "year must be greater than or equal to 1583 (1582 is start of Gregorian Calendar)" return (year % 4 == 0) and (year % 100 != 0 or year % 400 == 0) From 474d17f317d6c1bec66acdc78a229cdbf7b9249e Mon Sep 17 00:00:00 2001 From: Alexander Andom <121858703+aandom@users.noreply.github.com> Date: Wed, 1 Jan 2025 13:08:55 +0000 Subject: [PATCH 10/48] is-palindrome-ch-done #18 --- solutions/is_palindrome.py | 43 ++++++++++++++ solutions/tests/test_is_palindrome.py | 80 +++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 solutions/is_palindrome.py create mode 100644 solutions/tests/test_is_palindrome.py diff --git a/solutions/is_palindrome.py b/solutions/is_palindrome.py new file mode 100644 index 000000000..5dc413355 --- /dev/null +++ b/solutions/is_palindrome.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for checking if a string is a palindrome. + +A palindrome is a string that reads the same forwards and backwards,ignoring case and spaces. + +Module contents: + - is_palindrome(s): checks if a string is a palindrome. + +Created on 2024-01-01 +@author: Alexander Andom +""" + + +def is_palindrome(s: str) -> bool: + """ + Checks if the given string is a palindrome. + + Parameters: + s : str, The string to check. + + Returns: + bool: True if the string is a palindrome, False otherwise. + + Raises: + AssertionError: If the input is not a string. + + Examples: + >>> is_palindrome('madam') + True + + >>> is_palindrome('A man a plan a canal Panama') + True + + >>> is_palindrome('hello') + False + """ + + assert isinstance(s, str), "Input must be a string." + + s = s.replace(" ", "").lower() + return s == s[::-1] diff --git a/solutions/tests/test_is_palindrome.py b/solutions/tests/test_is_palindrome.py new file mode 100644 index 000000000..8a7b0332f --- /dev/null +++ b/solutions/tests/test_is_palindrome.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for testing the is_palindrome function. + +Test cases include: + - Valid palindromes: strings that are palindromes. + - Invalid palindromes: strings that are not palindromes. + - Edge cases: empty strings, single-character strings, strings with mixed cases or spaces. + - Invalid inputs: non-string values (e.g., integers or floats). + +Created on 2024-01-01 +@author: Alexander Andom +""" + +import unittest + +from ..is_palindrome import is_palindrome + + +class TestIsPalindrome(unittest.TestCase): + """Test the is_palindrome function""" + + def test_valid_palindrome_1(self): + """It should return True""" + result = is_palindrome("madam") + self.assertTrue(result) + + def test_valid_palindrome_2(self): + """It should return True""" + result = is_palindrome("racecar") + self.assertTrue(result) + + def test_valid_palindrome_3(self): + """This is should return True""" + result = is_palindrome("A man a plan a canal Panama") + self.assertTrue(result) + + def test_invalid_palindrome(self): + """It should return False""" + result = is_palindrome("hello") + self.assertFalse(result) + + def test_edge_case_empty_string(self): + """It should return True""" + result = is_palindrome("") + self.assertTrue(result) + + def test_edge_case_single_character(self): + """It should return True""" + result = is_palindrome("a") + self.assertTrue(result) + + def test_edge_case_spaces(self): + """It should return True)""" + result = is_palindrome("a b c b a") + self.assertTrue(result) + + def test_edge_case_mixed_case(self): + """It should return True""" + result = is_palindrome("MadAm") + self.assertTrue(result) + + def test_non_palindrome_mixed_characters(self): + """Test for non-palindrome with mixed characters""" + self.assertFalse(is_palindrome("Hello, world!")) + + def test_invalid_input_integer(self): + """This should raise an AssertionError""" + with self.assertRaises(AssertionError): + is_palindrome(12321) + + def test_invalid_input_float(self): + """This should raise an AssertionError""" + with self.assertRaises(AssertionError): + is_palindrome(123.21) + + +if __name__ == "__main__": + unittest.main() From ef371e95a2b82abab95f55f9051cf16362fe6227 Mon Sep 17 00:00:00 2001 From: Tbaosman <99553124+Tbaosman@users.noreply.github.com> Date: Wed, 1 Jan 2025 23:29:25 +0400 Subject: [PATCH 11/48] Done anagram checker challenge and its test file --- solutions/anagram_checker.py | 49 ++++++++++++++ solutions/tests/test_anagram_checker.py | 87 +++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 solutions/anagram_checker.py create mode 100644 solutions/tests/test_anagram_checker.py diff --git a/solutions/anagram_checker.py b/solutions/anagram_checker.py new file mode 100644 index 000000000..ee7da6c49 --- /dev/null +++ b/solutions/anagram_checker.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +A module to check if two strings are anagrams of each other. + +Module contents: + - anagram_checker: Function to check if two strings are anagrams of each other. + +Created on 01/01/2025 +@author: Mohamed Saeed + +""" + + +def anagram_checker(s1: str, s2: str) -> bool: + """ + Function to check if two strings are anagrams of each other. + + An anagram is a word or phrase formed by rearranging the letters of a different + word or phrase, typically using all the original letters exactly once. + + Parameters: + s1 (str): The first input string. + s2 (str): The second input string. + + Returns: + bool: True if the strings are anagrams, False otherwise. + + Raises: + assertionError: If the inputs are not strings. + + + Examples: + >>> anagram_checker("listen", "silent") + True + >>> anagram_checker("hello", "world") + False + >>> anagram_checker("rail safety", "fairy tales") + True + """ + assert isinstance(s1, str), "Input must be a string" + assert isinstance(s2, str), "Input must be a string" + assert len(s1) == len(s2), "Strings must have the same length." + + is_anagram = sorted(s1.replace(" ", "").lower()) == sorted( + s2.replace(" ", "").lower() + ) + return is_anagram diff --git a/solutions/tests/test_anagram_checker.py b/solutions/tests/test_anagram_checker.py new file mode 100644 index 000000000..e6878f9b0 --- /dev/null +++ b/solutions/tests/test_anagram_checker.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +test module for anagram_checker function. +Contains correct tests to help identify bugs in the implementation. + +Test categories: + - Standard cases: typical string inputs + - Edge cases: empty strings, equal strings + - Defensive tests: invalid inputs + +created on 2024-12-28 +author: Mohamed Saeed +""" + +import unittest + +from ..anagram_checker import anagram_checker + + +class TestAnagramChecker(unittest.TestCase): + """ + Test class for the anagram_checker function. + """ + + def test_standard_cases(self): + """ + Test the function with standard inputs. + """ + self.assertTrue(anagram_checker("listen", "silent")) + + def test_edge_cases(self): + """ + Test the function with edge inputs. + """ + self.assertFalse(anagram_checker("hello", "world")) + + def test_empty_strings(self): + """ + Test the function with empty strings. + """ + self.assertTrue(anagram_checker("", "")) + + def test_equal_strings(self): + """ + Test the function with equal strings. + """ + self.assertTrue(anagram_checker("hello", "hello")) + + def test_numbers_as_strings(self): + """ + Test the function with numbers as strings. + """ + self.assertTrue(anagram_checker("123", "321")) + + def test_special_characters(self): + """ + Test the function with special characters. + """ + self.assertTrue(anagram_checker("@#$!", "!@#$")) + + def test_combination(self): + """ + Test the function with a combination of numbers, letters, and special characters. + """ + self.assertTrue(anagram_checker("12@asd#$", "s@a#$12d")) + + def test_case_insensitive(self): + """ + Test the function with case-insensitive strings. + """ + self.assertTrue(anagram_checker("Rail safety", "Fairy tales")) + + def test_defensive_cases(self): + """ + Test the function with invalid inputs. + """ + with self.assertRaises(AssertionError): + anagram_checker(123, 456) + + def test_unequal_length(self): + """ + Test the function with unequal length strings. + """ + with self.assertRaises(AssertionError): + anagram_checker("hello", "worlds") From 5bbc6897168d5e29008c049c01216528663aa22a Mon Sep 17 00:00:00 2001 From: Alexander Andom <121858703+aandom@users.noreply.github.com> Date: Thu, 2 Jan 2025 13:36:54 +0000 Subject: [PATCH 12/48] binary-search-ch-done #22 --- solutions/binary_search.py | 69 ++++++++++++++++++ solutions/tests/test_binary_search.py | 101 ++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 solutions/binary_search.py create mode 100644 solutions/tests/test_binary_search.py diff --git a/solutions/binary_search.py b/solutions/binary_search.py new file mode 100644 index 000000000..d04434084 --- /dev/null +++ b/solutions/binary_search.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for performing binary search on a sorted list. + +Binary Searching is a searching algorithm used in a sorted array by repeatedly dividing the search +interval in half. It works by repeatedly dividing the search interval in half until the target value +is found or the interval is empty.. + +Module contents: + - binary_search(arr, item, start, end): Searches for an item in a sorted list + within a specified range using the binary search algorithm. + +Created on 2025-01-02 +@author: Alexander Andom +""" + + +def binary_search(arr: list[int], item: int, start: int, end: int): + """ + Perform binary search to find the index of an item in a sorted list. + + Parameters: + arr : list[int], A sorted list of integers to search within. + item : int, The target item to search for. + start : int, The starting index of the search range. + end : int, The ending index of the search range. + + Returns: + int: The index of the item if found; otherwise, -1. + + Raises: + AssertionError: + - If 'arr' is not a list. + - If 'item' is not an integer. + - If 'start' or 'end' are not integers or are negative. + - If the input list is not sorted in ascending order. + + Example: + >>> arr = [1, 2, 3, 4, 5] + >>> binary_search(arr, 3, 0, len(arr) - 1) + 2 + + >>> binary_search(arr, 6, 0, len(arr) - 1) + -1 + + >>> binary_search(arr, 1, 0, len(arr) - 1) + 0 + """ + + assert isinstance(arr, list), "Input 'arr' must be a list." + assert isinstance(item, int), "Input 'item' must be an integer." + assert isinstance(start, int), "Input 'start' must be an integer." + assert start >= 0, "Input 'start' must be greater than or equal to 0." + assert isinstance(end, int), "Input 'end' must be an integer." + assert end >= 0, "Input 'end' must be greater than or equal to 0." + assert arr == sorted(arr), "Input list must be sorted." + + if len(arr) < 1 or end < 0 or start < 0: + return -1 + if start > end: + return -1 + mid = start + (end - start) // 2 + if item == arr[mid]: + return mid + if item < arr[mid]: + return binary_search(arr, item, start, mid - 1) + + return binary_search(arr, item, mid + 1, end) diff --git a/solutions/tests/test_binary_search.py b/solutions/tests/test_binary_search.py new file mode 100644 index 000000000..f6143ddfa --- /dev/null +++ b/solutions/tests/test_binary_search.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for testing the binary_search function.. + +Test cases include: + - Valid inputs: Searching for elements within a sorted list. + - Edge cases: Searching for elements at the start, middle, or end of the list. + - Non-existent elements: Searching for elements not in the list. + - Invalid inputs: Providing invalid ranges or unsorted input. + +Created on 2025-01-02 +@author: Alexander Andom +""" + +import unittest + +from ..binary_search import binary_search + + +class TestBinarySearch(unittest.TestCase): + """Test the binary_search function""" + + def test_search_existing_middle(self): + """It should return the index of the item in the middle""" + arr = [1, 2, 3, 4, 5] + self.assertEqual(binary_search(arr, 3, 0, len(arr) - 1), 2) + + def test_search_existing_start(self): + """It should return the index of the item at the start""" + arr = [1, 2, 3, 4, 5] + self.assertEqual(binary_search(arr, 1, 0, len(arr) - 1), 0) + + def test_search_existing_end(self): + """It should return the index of the item at the end""" + arr = [1, 2, 3, 4, 5] + self.assertEqual(binary_search(arr, 5, 0, len(arr) - 1), 4) + + def test_search_nonexistent(self): + """It should return -1 for an item not in the list""" + arr = [1, 2, 3, 4, 5] + self.assertEqual(binary_search(arr, 6, 0, len(arr) - 1), -1) + + def test_search_invalid_range(self): + """It should return -1 for an invalid range""" + arr = [1, 2, 3, 4, 5] + self.assertEqual(binary_search(arr, 3, 3, 2), -1) + + def test_search_empty_list(self): + """It should return -1 for an empty list""" + arr = [] + self.assertEqual(binary_search(arr, 1, 0, 0), -1) + + def test_search_single_element_found(self): + """It should return the index for a single-element list""" + arr = [3] + self.assertEqual(binary_search(arr, 3, 0, 0), 0) + + def test_search_single_element_not_found(self): + """It should return -1 for a single-element list when the item is not found""" + arr = [3] + self.assertEqual(binary_search(arr, 4, 0, 0), -1) + + def test_invalid_arr(self): + """It should raise an assertion error if arr is not a list.""" + with self.assertRaises(AssertionError): + binary_search("not_a_list", 3, 0, 5) + + def test_invalid_item(self): + """It should raise an assertion error if item is not an integer.""" + with self.assertRaises(AssertionError): + binary_search([1, 2, 3], "3", 0, 2) + + def test_invalid_start_type(self): + """It should raise an assertion error if start is not an integer.""" + with self.assertRaises(AssertionError): + binary_search([1, 2, 3], 2, "start", 2) + + def test_invalid_start_value(self): + """It should raise an assertion error if start is negative.""" + with self.assertRaises(AssertionError): + binary_search([1, 2, 3], 2, -1, 2) + + def test_invalid_end_type(self): + """It should raise an assertion error if end is not an integer.""" + with self.assertRaises(AssertionError): + binary_search([1, 2, 3], 2, 0, "end") + + def test_invalid_end_value(self): + """It should raise an assertion error if end is negative.""" + with self.assertRaises(AssertionError): + binary_search([1, 2, 3], 2, 0, -2) + + def test_unsorted_list(self): + """It should raise an assertion error if the list is unsorted.""" + with self.assertRaises(AssertionError): + binary_search([3, 1, 2], 2, 0, 2) + + +if __name__ == "__main__": + unittest.main() From cb6cc1e7c4d6ec7692852454d6ce77d0d7cfe9cb Mon Sep 17 00:00:00 2001 From: tamirwaleed <135042104+tamirwaleed@users.noreply.github.com> Date: Thu, 2 Jan 2025 19:43:32 +0400 Subject: [PATCH 13/48] Updated Collaboration README.md with Group Norms --- collaboration/README.md | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/collaboration/README.md b/collaboration/README.md index 20889b951..984d2dd55 100644 --- a/collaboration/README.md +++ b/collaboration/README.md @@ -1,5 +1,40 @@ -# Collaboration +# 🐍 We're the PyRectifiers 🛠️ - +## *We're here to rectify your Pythons!* - +--- + +## 📜 Group Norms + +### ⏰ Respecting Each Other’s Time + +- Meetings will be scheduled **at least one day a week**, with a **48-hour prior agreement/announcement**. +- 🗳️ **Meeting times** will be voted on in Slack the day before. + +### 📡 Communication + +- **Maintain effective communication** on Slack—let’s keep the discussions flowing! 💬 +- Feel free to **ask for help**; we’re here to support each other! 🙌 + +### 🗓️ Meetings + +- **Prepare for meetings** with defined agendas beforehand to keep things efficient. +- **Use Google Meet** for a smoother meeting experience. 🎥 +- **Weekly milestones** will help us track progress. 🏁 +- **Internal milestone** will be Jan. 7 ⏱ + +### 🏗️ Repository Management + +- Follow **naming conventions** for challenges that reflect their behavior (e.g., a challenge to find the sum of 3 numbers should benamed `"sum of 3"`). +- Choose **1 or 2 people** to handle repository updates to ensure consistency. + +### 🔧 Collaboration Tips + +- Stay **active on Slack** to stay in the loop and contribute effectively. 🖇️ +- Let’s make meetings productive and focused—plan ahead to avoid unnecessary delays. + +--- + +## 🤝 Together, We’ll Rectify Pythons! 🐍✨ + +With great communication, preparation, and teamwork, we’ll tackle challenges and keep things rectified—just like PyRectifiers should! 🎉 From 503583409329d6cb173459fd9986c49dc2f4055b Mon Sep 17 00:00:00 2001 From: tamirwaleed <135042104+tamirwaleed@users.noreply.github.com> Date: Thu, 2 Jan 2025 19:48:51 +0400 Subject: [PATCH 14/48] Fixed typo in README.md --- collaboration/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collaboration/README.md b/collaboration/README.md index 984d2dd55..cb37b1f10 100644 --- a/collaboration/README.md +++ b/collaboration/README.md @@ -25,7 +25,7 @@ ### 🏗️ Repository Management -- Follow **naming conventions** for challenges that reflect their behavior (e.g., a challenge to find the sum of 3 numbers should benamed `"sum of 3"`). +- Follow **naming conventions** for challenges that reflect their behavior (e.g., a challenge to find the sum of 3 numbers should be named `"sum of 3"`). - Choose **1 or 2 people** to handle repository updates to ensure consistency. ### 🔧 Collaboration Tips From b4b887b3bec21235d77733a8b45d8d90f850930e Mon Sep 17 00:00:00 2001 From: tamirwaleed <135042104+tamirwaleed@users.noreply.github.com> Date: Thu, 2 Jan 2025 19:57:56 +0400 Subject: [PATCH 15/48] Fixed the CI/CD issues in README.md --- collaboration/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/collaboration/README.md b/collaboration/README.md index cb37b1f10..5f1c348aa 100644 --- a/collaboration/README.md +++ b/collaboration/README.md @@ -8,24 +8,26 @@ ### ⏰ Respecting Each Other’s Time -- Meetings will be scheduled **at least one day a week**, with a **48-hour prior agreement/announcement**. +- **Meetings** will be scheduled **at least one day a week**. +- **Additional Meetings** will be scheduled with a **48-hour prior agreement**. - 🗳️ **Meeting times** will be voted on in Slack the day before. ### 📡 Communication -- **Maintain effective communication** on Slack—let’s keep the discussions flowing! 💬 +- **Maintain communication** on Slack—let’s keep the discussions flowing! 💬 - Feel free to **ask for help**; we’re here to support each other! 🙌 ### 🗓️ Meetings -- **Prepare for meetings** with defined agendas beforehand to keep things efficient. +- **Prepare for meetings** with pre-defined agendas beforehand. - **Use Google Meet** for a smoother meeting experience. 🎥 - **Weekly milestones** will help us track progress. 🏁 - **Internal milestone** will be Jan. 7 ⏱ ### 🏗️ Repository Management -- Follow **naming conventions** for challenges that reflect their behavior (e.g., a challenge to find the sum of 3 numbers should be named `"sum of 3"`). +- Follow **naming conventions** for challenges that reflect their behavior. +- Preferably, the branches/issues will be named as _"GP25_challenge-name"_ - Choose **1 or 2 people** to handle repository updates to ensure consistency. ### 🔧 Collaboration Tips @@ -37,4 +39,5 @@ ## 🤝 Together, We’ll Rectify Pythons! 🐍✨ -With great communication, preparation, and teamwork, we’ll tackle challenges and keep things rectified—just like PyRectifiers should! 🎉 +With great communication, preparation, and teamwork? +We’ll keep things rectified—just like PyRectifiers should! 🎉 From 3d8f925c0ef9cbc18b5b863747c24bcf1552b65a Mon Sep 17 00:00:00 2001 From: tamirwaleed <135042104+tamirwaleed@users.noreply.github.com> Date: Thu, 2 Jan 2025 20:01:28 +0400 Subject: [PATCH 16/48] Fixed additional md linting in README.md --- collaboration/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/collaboration/README.md b/collaboration/README.md index 5f1c348aa..fee753ff9 100644 --- a/collaboration/README.md +++ b/collaboration/README.md @@ -9,7 +9,7 @@ ### ⏰ Respecting Each Other’s Time - **Meetings** will be scheduled **at least one day a week**. -- **Additional Meetings** will be scheduled with a **48-hour prior agreement**. +- **Additional Meetings** will be scheduled **48-hours** beforehand. - 🗳️ **Meeting times** will be voted on in Slack the day before. ### 📡 Communication @@ -27,17 +27,17 @@ ### 🏗️ Repository Management - Follow **naming conventions** for challenges that reflect their behavior. -- Preferably, the branches/issues will be named as _"GP25_challenge-name"_ +- Preferably, the branches/issues will be named as *"GP25_challenge-name"* - Choose **1 or 2 people** to handle repository updates to ensure consistency. ### 🔧 Collaboration Tips - Stay **active on Slack** to stay in the loop and contribute effectively. 🖇️ -- Let’s make meetings productive and focused—plan ahead to avoid unnecessary delays. +- Let’s make meetings productive and focused to avoid unnecessary delays. --- ## 🤝 Together, We’ll Rectify Pythons! 🐍✨ -With great communication, preparation, and teamwork? +With great communication, preparation, and teamwork? We’ll keep things rectified—just like PyRectifiers should! 🎉 From c26aea74fe1aff812849f4bf4c5fcfbbc92fa09b Mon Sep 17 00:00:00 2001 From: Dr-Amin-K Date: Fri, 3 Jan 2025 06:58:52 +0400 Subject: [PATCH 17/48] Done communication file --- collaboration/communication.md | 78 ++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/collaboration/communication.md b/collaboration/communication.md index 484652e0f..a54417d54 100644 --- a/collaboration/communication.md +++ b/collaboration/communication.md @@ -1,54 +1,68 @@ - +## Communication Schedule -# Communication +| Day | How | The topic of discussion | +|------------|------------------|------------------------------------| +| All | Slack | Various discussions | +| Sunday | Zoom/Google Meet | Introducing ourselves; Discussing Group Norms | +|(22/12/2024)| | | +| Tuesday | Google Meet | Discussing the Challenges (with a Demo) | +|(24/12/2024)| | | +| Friday|Google Meet|Discussing the Collaboration Documents and assigning members| +|(24/12/2024)| | Discussing the Challenges and working on the repository | +| Thursday | Google Meet | Discussing the work progress | +|(02/01/2025)| | | ______________________________________________________________________ -## Communication Schedule +## Communication Channels -| Day | How | The topic of discussion | | --- | :-: | ----------------------- | -| | | | +How often will we get in touch on each channel, and what we will discuss there: -## Communication Channels +- **Issues**: + - **Frequency**: As needed. + - **Purpose**: To track tasks, assign the responsibilities, and report the bugs. -how often will we get in touch on each channel, and what we will discuss there: +- **Pull Requests**: + - **Frequency**: Daily. + - **Purpose**: To share the codes and documents, review the contributions, + and approve changes. -- **Issues**: -- **Pull Requests**: -- **Slack/Discord**: -- **Video Calls**: +- **Slack**: + - **Frequency**: Daily. + - **Purpose**: To ask questions and provide answers, and to update the group members + on the work and the meetings. + +- **Video Calls**: + - **Frequency**: As discussed (often, twice a week). + - **Purpose**: To discuss the collaborative work in detail, and to organize + and plan the upcoming steps and future work. ______________________________________________________________________ ## Availability ### Availability for calling/messaging - -| Day | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday | | ------- | :----: | :-----: | :-------: | :------: | :----: | :------: | :----: | -| _name_ | | | | | | | | + +| Days | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday | +|------------|:-------:|:--------:|:----------:|:---------:|:-------:|:---------:|:-------:| +| Amin Abd Elraheem | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | +| Mohamed Saeed | 9am-3pm| 9am-3pm | 9am-3pm | 9am-3pm | 9am-3pm| 9am-3pm | 9am-3pm| +| Name | ... | ... | ... | ... | ... | ... | ... | ### How many hours everyone has per day -- name: _5h_; -- name: _6h_; -- name: _5h_; -- name: _4h_; -- name: _3h_; +- Amin Abd Elraheem: _5hrs_ +- Mohamed Saeed: _6hrs_ +- Name: _...hrs_ ## Asking for Help -There's a fine line between confidently learning from your mistakes, and -stubbornly getting no where. Here is a general guide for when to ask for help -based on how long you've been stuck on the same problem: +There's a fine line between confidently learning from your mistakes, +and stubbornly getting nowhere. Here is a general guide for when to +ask for help based on how long you've been stuck on the same problem: -1. _0 -> 30 min_: Try on your own -1. _30 -> 60 min_: Ask your group for help -1. _60+ min_: Tag your coaches in Slack or GitHub +1. **0 -> 30 min**: Try on your own. +2. **30 -> 60 min**: Ask your group for help. +3. **60+ min**: Tag your coaches in Slack or GitHub. From 5e8286108686ead61c0aac44d99449c7df4ed8cd Mon Sep 17 00:00:00 2001 From: Dr-Amin-K Date: Sat, 4 Jan 2025 21:54:33 +0400 Subject: [PATCH 18/48] corrected --- collaboration/communication.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/collaboration/communication.md b/collaboration/communication.md index a54417d54..62ed14d36 100644 --- a/collaboration/communication.md +++ b/collaboration/communication.md @@ -2,17 +2,18 @@ ## Communication Schedule -| Day | How | The topic of discussion | -|------------|------------------|------------------------------------| -| All | Slack | Various discussions | -| Sunday | Zoom/Google Meet | Introducing ourselves; Discussing Group Norms | -|(22/12/2024)| | | -| Tuesday | Google Meet | Discussing the Challenges (with a Demo) | -|(24/12/2024)| | | -| Friday|Google Meet|Discussing the Collaboration Documents and assigning members| -|(24/12/2024)| | Discussing the Challenges and working on the repository | -| Thursday | Google Meet | Discussing the work progress | -|(02/01/2025)| | | +| Day | How | The topic of discussion | +|------------|------------------|-----------------------------------------------| +| All | Slack | Various discussions | +| Sunday | Zoom/Google Meet | Introducing ourselves; Discussing Group Norms | +|(22/12/2024)| | | +| Tuesday | Google Meet | Discussing the Challenges (with a Demo) | +|(24/12/2024)| | | +| Friday |Google Meet | Discussing the Collaboration Documents, | +|(27/12/2024)| | assigning members, discussing the Challenges, | +| | | and working on the repository | +| Thursday | Google Meet | Discussing the work progress | +|(02/01/2025)| | | ______________________________________________________________________ @@ -45,11 +46,11 @@ ______________________________________________________________________ ### Availability for calling/messaging -| Days | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday | -|------------|:-------:|:--------:|:----------:|:---------:|:-------:|:---------:|:-------:| -| Amin Abd Elraheem | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | -| Mohamed Saeed | 9am-3pm| 9am-3pm | 9am-3pm | 9am-3pm | 9am-3pm| 9am-3pm | 9am-3pm| -| Name | ... | ... | ... | ... | ... | ... | ... | +| Days | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday | +|-------------------------|:-------:|:--------:|:----------:|:---------:|:-------:|:---------:|:-------:| +| Amin Abd Elraheem | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | 9am-2pm | +| Mohamed Saeed | 9am-3pm | 9am-3pm | 9am-3pm | 9am-3pm | 9am-3pm | 9am-3pm | 9am-3pm | +| Name | ... | ... | ... | ... | ... | ... | ... | ### How many hours everyone has per day From 36eec0f5cb918d6727223a99d39ccf8e1f5b6dca Mon Sep 17 00:00:00 2001 From: Tbaosman <99553124+Tbaosman@users.noreply.github.com> Date: Sun, 5 Jan 2025 02:11:06 +0400 Subject: [PATCH 19/48] Done multiplication table challenge with its test file --- solutions/multiplication_table.py | 60 ++ solutions/tests/test_multiplication_table.py | 967 +++++++++++++++++++ 2 files changed, 1027 insertions(+) create mode 100644 solutions/multiplication_table.py create mode 100644 solutions/tests/test_multiplication_table.py diff --git a/solutions/multiplication_table.py b/solutions/multiplication_table.py new file mode 100644 index 000000000..c8a485b64 --- /dev/null +++ b/solutions/multiplication_table.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This module contains a function to generate a multiplication table. +module contents: + - multiplication_table: Function to generate a multiplication table from 1 up to n. + +created on 05/01/2025 #dd/mm/yyyy +@author: Mohamed Saeed +""" + + +def multiplication_table(number: int, length: int) -> list: + """ + Function to generate a multiplication table. + + A multiplication table is a table of numbers that shows the results of + multiplying two numbers together. + + Parameters: + number (int): The number to generate the multiplication table for. + length (int): The length or range of the multiplication table. + + Returns: + list: A list of integers representing the multiplication table. + + Raises: + assertionError: If the input number is not an integer. + assertionError: If the input length (range) is not an integer. + assertionError: If the input number is not a positive integer. + assertionError: If the input length (range) is not a positive integer. + ValueError: If the input number is too large. + ValueError: If the input range is too large. + + Examples: + >>> multiplication_table(1, 5) + [1, 2, 3, 4, 5] + >>> multiplication_table(5, 10) + [5, 10, 15, 20, 25, 30, 35, 40, 45, 50] + >>> multiplication_table(7, 3) + [7, 14, 21] + """ + max_upper_limit = 1000 + + assert isinstance(number, int), "Input number must be an integer" + assert isinstance(length, int), "Input length must be an integer" + assert number > 0, "Number input must be a positive integer" + assert length > 0, "length input must be a positive integer" + assert number is not None, "Number input must not be None" + assert length is not None, "length input must not be None" + if number > max_upper_limit: + raise ValueError("Input number is too large") + if length > max_upper_limit: + raise ValueError("Input length is too large") + + table = [] + for j in range(1, length + 1): + product = number * j + table.append(product) + return table diff --git a/solutions/tests/test_multiplication_table.py b/solutions/tests/test_multiplication_table.py new file mode 100644 index 000000000..34b2dda93 --- /dev/null +++ b/solutions/tests/test_multiplication_table.py @@ -0,0 +1,967 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" " +Test module for multiplication_table function. +Contains correct tests to help identify bugs in the implementation. + +Test categories: + - Standard cases: typical integer inputs + - Edge cases: empty input , large numbers + - Defensive tests: invalid inputs + +Created on 05/01/2025 #dd/mm/yyyy +Author: Mohamed Saeed +""" + +import unittest + +from ..multiplication_table import multiplication_table + + +class TestMultiplicationTable(unittest.TestCase): + """ + Test class for the multiplication_table function. + """ + + def test_normal_case(self): + """ + Test the function with a standard input. + """ + self.assertEqual(multiplication_table(3, 5), [3, 6, 9, 12, 15]) + + def test_edge_case1(self): + """ + Test the function with an edge input smallest numbers. + """ + self.assertEqual(multiplication_table(1, 1), [1]) + + def test_none_number_input(self): + """ + Test the function with a None number input. + """ + with self.assertRaises(AssertionError): + multiplication_table(None, 5) + + def test_none_length_input(self): + """ + Test the function with a None length input. + """ + with self.assertRaises(AssertionError): + multiplication_table(3, None) + + def test_empty_input(self): + """ + Test the function with an empty input. + """ + with self.assertRaises(AssertionError): + multiplication_table("", "") + + def test_string_number_input(self): + """ + Test the function with an string number input. + """ + with self.assertRaises(AssertionError): + multiplication_table("3", 5) + + def test_string_until_input(self): + """ + Test the function with an string length input. + """ + with self.assertRaises(AssertionError): + multiplication_table(3, "5") + + def test_negative_input1(self): + """ + Test the function with a negative number input. + """ + with self.assertRaises(AssertionError): + multiplication_table(-3, 5) + + def test_negative_input2(self): + """ + Test the function with a negative length input. + """ + with self.assertRaises(AssertionError): + multiplication_table(3, -5) + + def test_large_input_number(self): + """ + Test the function with large input numbers. + """ + with self.assertRaises(ValueError): + multiplication_table(1001, 5) + + def test_large_input_until(self): + """ + Test the function with large length numbers. + """ + with self.assertRaises(ValueError): + multiplication_table(3, 1001) + + def test_large_input_both(self): + """ + Test the function with large input & length numbers. + """ + with self.assertRaises(ValueError): + multiplication_table(1001, 1001) + + def test_edge_case2(self): + """ + Test the function with an edge input very large numbers. + """ + self.assertEqual( + multiplication_table(900, 850), + [ + 900, + 1800, + 2700, + 3600, + 4500, + 5400, + 6300, + 7200, + 8100, + 9000, + 9900, + 10800, + 11700, + 12600, + 13500, + 14400, + 15300, + 16200, + 17100, + 18000, + 18900, + 19800, + 20700, + 21600, + 22500, + 23400, + 24300, + 25200, + 26100, + 27000, + 27900, + 28800, + 29700, + 30600, + 31500, + 32400, + 33300, + 34200, + 35100, + 36000, + 36900, + 37800, + 38700, + 39600, + 40500, + 41400, + 42300, + 43200, + 44100, + 45000, + 45900, + 46800, + 47700, + 48600, + 49500, + 50400, + 51300, + 52200, + 53100, + 54000, + 54900, + 55800, + 56700, + 57600, + 58500, + 59400, + 60300, + 61200, + 62100, + 63000, + 63900, + 64800, + 65700, + 66600, + 67500, + 68400, + 69300, + 70200, + 71100, + 72000, + 72900, + 73800, + 74700, + 75600, + 76500, + 77400, + 78300, + 79200, + 80100, + 81000, + 81900, + 82800, + 83700, + 84600, + 85500, + 86400, + 87300, + 88200, + 89100, + 90000, + 90900, + 91800, + 92700, + 93600, + 94500, + 95400, + 96300, + 97200, + 98100, + 99000, + 99900, + 100800, + 101700, + 102600, + 103500, + 104400, + 105300, + 106200, + 107100, + 108000, + 108900, + 109800, + 110700, + 111600, + 112500, + 113400, + 114300, + 115200, + 116100, + 117000, + 117900, + 118800, + 119700, + 120600, + 121500, + 122400, + 123300, + 124200, + 125100, + 126000, + 126900, + 127800, + 128700, + 129600, + 130500, + 131400, + 132300, + 133200, + 134100, + 135000, + 135900, + 136800, + 137700, + 138600, + 139500, + 140400, + 141300, + 142200, + 143100, + 144000, + 144900, + 145800, + 146700, + 147600, + 148500, + 149400, + 150300, + 151200, + 152100, + 153000, + 153900, + 154800, + 155700, + 156600, + 157500, + 158400, + 159300, + 160200, + 161100, + 162000, + 162900, + 163800, + 164700, + 165600, + 166500, + 167400, + 168300, + 169200, + 170100, + 171000, + 171900, + 172800, + 173700, + 174600, + 175500, + 176400, + 177300, + 178200, + 179100, + 180000, + 180900, + 181800, + 182700, + 183600, + 184500, + 185400, + 186300, + 187200, + 188100, + 189000, + 189900, + 190800, + 191700, + 192600, + 193500, + 194400, + 195300, + 196200, + 197100, + 198000, + 198900, + 199800, + 200700, + 201600, + 202500, + 203400, + 204300, + 205200, + 206100, + 207000, + 207900, + 208800, + 209700, + 210600, + 211500, + 212400, + 213300, + 214200, + 215100, + 216000, + 216900, + 217800, + 218700, + 219600, + 220500, + 221400, + 222300, + 223200, + 224100, + 225000, + 225900, + 226800, + 227700, + 228600, + 229500, + 230400, + 231300, + 232200, + 233100, + 234000, + 234900, + 235800, + 236700, + 237600, + 238500, + 239400, + 240300, + 241200, + 242100, + 243000, + 243900, + 244800, + 245700, + 246600, + 247500, + 248400, + 249300, + 250200, + 251100, + 252000, + 252900, + 253800, + 254700, + 255600, + 256500, + 257400, + 258300, + 259200, + 260100, + 261000, + 261900, + 262800, + 263700, + 264600, + 265500, + 266400, + 267300, + 268200, + 269100, + 270000, + 270900, + 271800, + 272700, + 273600, + 274500, + 275400, + 276300, + 277200, + 278100, + 279000, + 279900, + 280800, + 281700, + 282600, + 283500, + 284400, + 285300, + 286200, + 287100, + 288000, + 288900, + 289800, + 290700, + 291600, + 292500, + 293400, + 294300, + 295200, + 296100, + 297000, + 297900, + 298800, + 299700, + 300600, + 301500, + 302400, + 303300, + 304200, + 305100, + 306000, + 306900, + 307800, + 308700, + 309600, + 310500, + 311400, + 312300, + 313200, + 314100, + 315000, + 315900, + 316800, + 317700, + 318600, + 319500, + 320400, + 321300, + 322200, + 323100, + 324000, + 324900, + 325800, + 326700, + 327600, + 328500, + 329400, + 330300, + 331200, + 332100, + 333000, + 333900, + 334800, + 335700, + 336600, + 337500, + 338400, + 339300, + 340200, + 341100, + 342000, + 342900, + 343800, + 344700, + 345600, + 346500, + 347400, + 348300, + 349200, + 350100, + 351000, + 351900, + 352800, + 353700, + 354600, + 355500, + 356400, + 357300, + 358200, + 359100, + 360000, + 360900, + 361800, + 362700, + 363600, + 364500, + 365400, + 366300, + 367200, + 368100, + 369000, + 369900, + 370800, + 371700, + 372600, + 373500, + 374400, + 375300, + 376200, + 377100, + 378000, + 378900, + 379800, + 380700, + 381600, + 382500, + 383400, + 384300, + 385200, + 386100, + 387000, + 387900, + 388800, + 389700, + 390600, + 391500, + 392400, + 393300, + 394200, + 395100, + 396000, + 396900, + 397800, + 398700, + 399600, + 400500, + 401400, + 402300, + 403200, + 404100, + 405000, + 405900, + 406800, + 407700, + 408600, + 409500, + 410400, + 411300, + 412200, + 413100, + 414000, + 414900, + 415800, + 416700, + 417600, + 418500, + 419400, + 420300, + 421200, + 422100, + 423000, + 423900, + 424800, + 425700, + 426600, + 427500, + 428400, + 429300, + 430200, + 431100, + 432000, + 432900, + 433800, + 434700, + 435600, + 436500, + 437400, + 438300, + 439200, + 440100, + 441000, + 441900, + 442800, + 443700, + 444600, + 445500, + 446400, + 447300, + 448200, + 449100, + 450000, + 450900, + 451800, + 452700, + 453600, + 454500, + 455400, + 456300, + 457200, + 458100, + 459000, + 459900, + 460800, + 461700, + 462600, + 463500, + 464400, + 465300, + 466200, + 467100, + 468000, + 468900, + 469800, + 470700, + 471600, + 472500, + 473400, + 474300, + 475200, + 476100, + 477000, + 477900, + 478800, + 479700, + 480600, + 481500, + 482400, + 483300, + 484200, + 485100, + 486000, + 486900, + 487800, + 488700, + 489600, + 490500, + 491400, + 492300, + 493200, + 494100, + 495000, + 495900, + 496800, + 497700, + 498600, + 499500, + 500400, + 501300, + 502200, + 503100, + 504000, + 504900, + 505800, + 506700, + 507600, + 508500, + 509400, + 510300, + 511200, + 512100, + 513000, + 513900, + 514800, + 515700, + 516600, + 517500, + 518400, + 519300, + 520200, + 521100, + 522000, + 522900, + 523800, + 524700, + 525600, + 526500, + 527400, + 528300, + 529200, + 530100, + 531000, + 531900, + 532800, + 533700, + 534600, + 535500, + 536400, + 537300, + 538200, + 539100, + 540000, + 540900, + 541800, + 542700, + 543600, + 544500, + 545400, + 546300, + 547200, + 548100, + 549000, + 549900, + 550800, + 551700, + 552600, + 553500, + 554400, + 555300, + 556200, + 557100, + 558000, + 558900, + 559800, + 560700, + 561600, + 562500, + 563400, + 564300, + 565200, + 566100, + 567000, + 567900, + 568800, + 569700, + 570600, + 571500, + 572400, + 573300, + 574200, + 575100, + 576000, + 576900, + 577800, + 578700, + 579600, + 580500, + 581400, + 582300, + 583200, + 584100, + 585000, + 585900, + 586800, + 587700, + 588600, + 589500, + 590400, + 591300, + 592200, + 593100, + 594000, + 594900, + 595800, + 596700, + 597600, + 598500, + 599400, + 600300, + 601200, + 602100, + 603000, + 603900, + 604800, + 605700, + 606600, + 607500, + 608400, + 609300, + 610200, + 611100, + 612000, + 612900, + 613800, + 614700, + 615600, + 616500, + 617400, + 618300, + 619200, + 620100, + 621000, + 621900, + 622800, + 623700, + 624600, + 625500, + 626400, + 627300, + 628200, + 629100, + 630000, + 630900, + 631800, + 632700, + 633600, + 634500, + 635400, + 636300, + 637200, + 638100, + 639000, + 639900, + 640800, + 641700, + 642600, + 643500, + 644400, + 645300, + 646200, + 647100, + 648000, + 648900, + 649800, + 650700, + 651600, + 652500, + 653400, + 654300, + 655200, + 656100, + 657000, + 657900, + 658800, + 659700, + 660600, + 661500, + 662400, + 663300, + 664200, + 665100, + 666000, + 666900, + 667800, + 668700, + 669600, + 670500, + 671400, + 672300, + 673200, + 674100, + 675000, + 675900, + 676800, + 677700, + 678600, + 679500, + 680400, + 681300, + 682200, + 683100, + 684000, + 684900, + 685800, + 686700, + 687600, + 688500, + 689400, + 690300, + 691200, + 692100, + 693000, + 693900, + 694800, + 695700, + 696600, + 697500, + 698400, + 699300, + 700200, + 701100, + 702000, + 702900, + 703800, + 704700, + 705600, + 706500, + 707400, + 708300, + 709200, + 710100, + 711000, + 711900, + 712800, + 713700, + 714600, + 715500, + 716400, + 717300, + 718200, + 719100, + 720000, + 720900, + 721800, + 722700, + 723600, + 724500, + 725400, + 726300, + 727200, + 728100, + 729000, + 729900, + 730800, + 731700, + 732600, + 733500, + 734400, + 735300, + 736200, + 737100, + 738000, + 738900, + 739800, + 740700, + 741600, + 742500, + 743400, + 744300, + 745200, + 746100, + 747000, + 747900, + 748800, + 749700, + 750600, + 751500, + 752400, + 753300, + 754200, + 755100, + 756000, + 756900, + 757800, + 758700, + 759600, + 760500, + 761400, + 762300, + 763200, + 764100, + 765000, + ], + ) From 8d479baa45eded7f95461719984b77e8ee4db28e Mon Sep 17 00:00:00 2001 From: Dr-Amin-K Date: Sun, 5 Jan 2025 03:23:22 +0400 Subject: [PATCH 20/48] Done count capitalized words challenge and its test file --- solutions/count_capitalized_words.py | 41 +++++++++++++++ .../tests/test_count_capitalized_words.py | 51 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 solutions/count_capitalized_words.py create mode 100644 solutions/tests/test_count_capitalized_words.py diff --git a/solutions/count_capitalized_words.py b/solutions/count_capitalized_words.py new file mode 100644 index 000000000..ff1c5f3a2 --- /dev/null +++ b/solutions/count_capitalized_words.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for counting the words that begin with a capital letter (an uppercase letter) in a string. + +Module contents: + - count_capitalized_words: counts the words that begin with an uppercase letter in a string. + +Created on 05/01/2025 +@author: Amin +""" + + +def count_capitalized_words(text: str) -> int: + """Count the number of words that begin with an uppercase letter in a string. + + Parameters: + text: str, the input string to check + + Returns -> int: the number of words beginning with a capital letter in the text + + Raises: + AssertionError: if the argument is not a string + + >>> count_capitalized_words("word") + 0 + >>> count_capitalized_words("One more") + 1 + >>> count_capitalized_words("A B C") + 3 + """ + assert isinstance(text, str), "input must be a string" + + count = 0 + # Transform the original text into a list by splitting it + words = text.split() + # Loop through each element and count the capitalized words by checking the first letter + for i in words: + if i[0] == i[0].upper(): + count += 1 + return count diff --git a/solutions/tests/test_count_capitalized_words.py b/solutions/tests/test_count_capitalized_words.py new file mode 100644 index 000000000..d3108d945 --- /dev/null +++ b/solutions/tests/test_count_capitalized_words.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for testing the count_capitalized_words function. + +Test cases include: + - Strings with capitalized words. + - Strings without capitalized words. + - Edge cases: empty strings, single-character strings, strings with mixed cases. + - Invalid inputs: non-string values (e.g., integers or floats). + +Created on 05/01/2025 +@author: Amin +""" + +import unittest + +from ..count_capitalized_words import count_capitalized_words + + +class TestCountCapitalizedWords(unittest.TestCase): + """Test the count_capitalized_words function""" + + def test_empty_string(self): + """It should return 0 for an empty string""" + self.assertEqual(count_capitalized_words(""), 0) + + def test_single_uppercase_character_string(self): + """It should return 1 for a string that contain a single uppercase character""" + self.assertEqual(count_capitalized_words("A"), 1) + + def test_no_uppercase(self): + """It should return 0 for strings without words starting with uppercase""" + self.assertEqual(count_capitalized_words("yes"), 0) + + def test_all_capitalized(self): + """It should count all the words in the string""" + self.assertEqual(count_capitalized_words("A Capitalized Sentence"), 3) + + def test_mixed_case(self): + """It should handle strings with words of mixed characters""" + self.assertEqual(count_capitalized_words("Happy new year"), 1) + + def test_uppercase_not_the_first_letter(self): + """It should return 0 if there is and uppercase but not as the first letter of a word""" + self.assertEqual(count_capitalized_words("this is an eXample"), 0) + + def test_not_string(self): + """It should raise AssertionError for non-string input""" + with self.assertRaises(AssertionError): + count_capitalized_words(101) From fb156bee69bc1cb926f4869720043f772cedca9f Mon Sep 17 00:00:00 2001 From: Alaa Date: Sun, 5 Jan 2025 19:15:18 +0200 Subject: [PATCH 21/48] completed prime numbers challenge --- solutions/prime_numbers.py | 52 ++++++++++++++++++++++++++ solutions/tests/test_prime_numbers.py | 53 +++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 solutions/prime_numbers.py create mode 100644 solutions/tests/test_prime_numbers.py diff --git a/solutions/prime_numbers.py b/solutions/prime_numbers.py new file mode 100644 index 000000000..45ee42bfe --- /dev/null +++ b/solutions/prime_numbers.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" + +A module that determines whether a given number is a prime number. + +Module contents: + - is_prime: checks if the given number is a prime number. + +created on 04/01/2025 +@author: Alaa Mohamed + +""" + + +def is_prime(N: int) -> bool: + """ + Checks if the given number is a prime number. + A number is considered prime if it's only divisible by one and itself. + + + Parameters: + N: input must be an integer. + + Returns -> bool: True if the number is prime, False otherwise. + + Raises: + AssertionError: if the inout is not an integer. + + Examples: + >>> is_prime("1") + False + >>> is_prime("2") + True + >>> is_prime("3") + True + """ + assert isinstance(N, int), "input must be an integer" + + if N <= 1: + return False + for i in range(2, N): + if N % i == 0: + return False + return True + + +number = int(input("Enter a number: ")) +if is_prime(number): + print(f"{number} is a prime number.") +else: + print(f"{number} is not a prime number.") diff --git a/solutions/tests/test_prime_numbers.py b/solutions/tests/test_prime_numbers.py new file mode 100644 index 000000000..af0161625 --- /dev/null +++ b/solutions/tests/test_prime_numbers.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Test module for prime_numbers function. +Checks if the given number is a prime number. + +Test categories: + - Standard cases: typical integer inputs. + - Edge cases: special numbers such as 0 and 1. + - Defensive tests: invalid inputs. + +Created on 2025-01-04 +Author: Alaa Mohamed +""" + +import unittest + +from ..prime_numbers import prime_numbers + + +class TestPrimeNumbers(unittest.TestCase): + """ + + Test case for the prime_numbers function. + + """ + + +def test_not_int(self): + """It should raise AssertionError for non-integer input""" + with self.assertRaises(AssertionError): + prime_numbers(1.5) + + +def test_edge_case(self): + """Testing the function with edge inputs""" + self.assertFalse(prime_numbers(1)) + self.assertFalse(prime_numbers(0)) + + +def test_negative_numbers(self): + """Testing the function with negative inputs""" + self.AssertFalse(prime_numbers(-5)) + + +def test_large_prime_numbers(self): + """Testing the function with large prime numbers""" + self.assertTrue(prime_numbers(7919)) + + +def test_large_non_prime_numbers(self): + """Testing the function with large non-prime numbers""" + self.assertFalse(prime_numbers(100000)) From 06fd29c450b93561561bec32610d48d9b1d09c3b Mon Sep 17 00:00:00 2001 From: Alaa Date: Sun, 5 Jan 2025 19:31:20 +0200 Subject: [PATCH 22/48] made a slight change to pass CI checks --- solutions/prime_numbers.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/solutions/prime_numbers.py b/solutions/prime_numbers.py index 45ee42bfe..54cf21a1e 100644 --- a/solutions/prime_numbers.py +++ b/solutions/prime_numbers.py @@ -43,10 +43,3 @@ def is_prime(N: int) -> bool: if N % i == 0: return False return True - - -number = int(input("Enter a number: ")) -if is_prime(number): - print(f"{number} is a prime number.") -else: - print(f"{number} is not a prime number.") From 58c7eb3f4fa4257b2105457c9b2a9689c882ad31 Mon Sep 17 00:00:00 2001 From: Alaa Date: Sun, 5 Jan 2025 20:21:05 +0200 Subject: [PATCH 23/48] edited to pass py tests --- solutions/prime_numbers.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/solutions/prime_numbers.py b/solutions/prime_numbers.py index 54cf21a1e..a6d1af9ed 100644 --- a/solutions/prime_numbers.py +++ b/solutions/prime_numbers.py @@ -5,7 +5,7 @@ A module that determines whether a given number is a prime number. Module contents: - - is_prime: checks if the given number is a prime number. + - prime_numbers: checks if the given number is a prime number. created on 04/01/2025 @author: Alaa Mohamed @@ -13,33 +13,33 @@ """ -def is_prime(N: int) -> bool: +def prime_numbers(number: int) -> bool: """ Checks if the given number is a prime number. A number is considered prime if it's only divisible by one and itself. Parameters: - N: input must be an integer. + number: input must be an integer. Returns -> bool: True if the number is prime, False otherwise. Raises: - AssertionError: if the inout is not an integer. + AssertionError: if the input is not an integer. Examples: - >>> is_prime("1") + >>> prime_numbers("1") False - >>> is_prime("2") + >>> prime_numbers("2") True - >>> is_prime("3") + >>> prime_numbers("3") True """ - assert isinstance(N, int), "input must be an integer" + assert isinstance(number, int), "input must be an integer" - if N <= 1: + if number <= 1: return False - for i in range(2, N): - if N % i == 0: + for i in range(2, number): + if number % i == 0: return False return True From a7ca8ae22b5f83f8759ecef79b91c44a6a780356 Mon Sep 17 00:00:00 2001 From: Alaa Date: Sun, 5 Jan 2025 20:34:33 +0200 Subject: [PATCH 24/48] completed missing number challenge --- solutions/missing_number.py | 48 ++++++++++++++++++++++ solutions/tests/test_missing_number.py | 57 ++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 solutions/missing_number.py create mode 100644 solutions/tests/test_missing_number.py diff --git a/solutions/missing_number.py b/solutions/missing_number.py new file mode 100644 index 000000000..7ae9e4ae4 --- /dev/null +++ b/solutions/missing_number.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" + +A module that determines which number is missing out of a list. + +Module contents: + - missing_number: finds the missing number from a list. + +created on 04/01/2025 +@author: Alaa Mohamed + +""" + + +def missing_number(nums: list, n: int) -> int: + """Finds the missing numbers out of a list. + + Parameters: + nums: list, starting with zero and of any length + n: int, greater than or equal to zero + + Returns: + list: with the missing numbers. + + Raises: + AssertionError: if one of the arguments is invalid. + + Examples: + >>> missing_number([0,2], 3) + [1] + >>> missing_number([0,1,3], 5) + [2,4] + + """ + # the nums length should be an integer greater than 0 + assert n >= 0, "n must be greater than or equal to zero" + + full_set = set(range(n + 1)) + # The expected set of numbers is from 0 to n + + nums_set = set(nums) + # The actual set of numbers present in the 'nums' list + + missing = list(full_set - nums_set) + # The missing numbers are the difference between the full set and the actual set + + return missing diff --git a/solutions/tests/test_missing_number.py b/solutions/tests/test_missing_number.py new file mode 100644 index 000000000..352a5d390 --- /dev/null +++ b/solutions/tests/test_missing_number.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import unittest + +from ..missing_number import missing_number + + +class TestMissingNumber(unittest.TestCase): + """ + Test module for missing_number function. + Checks with numbers are missed out of a sequence. + + Test categories: + - Standard cases: only one missing value. + - Edge cases: empty list and list with one number. + - Defensive tests: invalid inputs or duplicate values. + + Created on 2025-01-04 + Author: Alaa Mohamed + """ + + +def test_only_one_missing_number(self): + "The list is [0, 1, 3] and n is 3" + "Missing number should be [2]" + self.assertEqual(missing_number([0, 1, 3], 3), [2]) + + +def test_an_empty_list(self): + "The list is [] and n is 0" + "Missing number should be [0]" + self.assertEqual(missing_number([], 0), [0]) + + +def test_list_with_one_number(self): + "The list is [0] and n is 1" + "Missing number should be [1]" + self.assertEqual(missing_number([0], 1), [1]) + + +def test_with_two_missing_numbers(self): + "The list is [1, 3, 5] and n is 5" + "Missing number should be [2, 4]" + self.assertEqual(missing_number([1, 3, 5], 5), [0, 2, 4]) + + +def test_list_with_no_missing_number(self): + "The list is [0, 1, 2] and n is 2" + "Missing number should be []" + self.assertEqual(missing_number([0, 1, 2], 2), []) + + +def test_duplicate_numbers(self): + "The list is [0, 1, 2, 2, 3, 4] and n is 4" + "Missing number should be []" + self.assertEqual(missing_number([0, 1, 2, 2, 3, 4], 4), []) From 72da85c202cade645a81583aaf174cf3c87d2ca0 Mon Sep 17 00:00:00 2001 From: Alaa Date: Mon, 6 Jan 2025 16:28:25 +0200 Subject: [PATCH 25/48] edited according to what my reviewer commented --- solutions/prime_numbers.py | 8 ++++---- solutions/tests/test_prime_numbers.py | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/solutions/prime_numbers.py b/solutions/prime_numbers.py index a6d1af9ed..7675f7971 100644 --- a/solutions/prime_numbers.py +++ b/solutions/prime_numbers.py @@ -28,11 +28,11 @@ def prime_numbers(number: int) -> bool: AssertionError: if the input is not an integer. Examples: - >>> prime_numbers("1") + >>> prime_numbers(1) False - >>> prime_numbers("2") + >>> prime_numbers(2) True - >>> prime_numbers("3") + >>> prime_numbers(3) True """ assert isinstance(number, int), "input must be an integer" @@ -42,4 +42,4 @@ def prime_numbers(number: int) -> bool: for i in range(2, number): if number % i == 0: return False - return True + return True diff --git a/solutions/tests/test_prime_numbers.py b/solutions/tests/test_prime_numbers.py index af0161625..a2a0843bf 100644 --- a/solutions/tests/test_prime_numbers.py +++ b/solutions/tests/test_prime_numbers.py @@ -35,7 +35,6 @@ def test_not_int(self): def test_edge_case(self): """Testing the function with edge inputs""" self.assertFalse(prime_numbers(1)) - self.assertFalse(prime_numbers(0)) def test_negative_numbers(self): From f0d91cf9f8a421d00f069f00354c4fcae1765873 Mon Sep 17 00:00:00 2001 From: Alaa Date: Mon, 6 Jan 2025 19:42:25 +0200 Subject: [PATCH 26/48] ready and set for review again --- solutions/missing_number.py | 15 +++-- solutions/tests/test_missing_number.py | 81 ++++++++++++++------------ 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/solutions/missing_number.py b/solutions/missing_number.py index 7ae9e4ae4..e94f20ab1 100644 --- a/solutions/missing_number.py +++ b/solutions/missing_number.py @@ -18,7 +18,7 @@ def missing_number(nums: list, n: int) -> int: Parameters: nums: list, starting with zero and of any length - n: int, greater than or equal to zero + n: int, nums length should be greater than or equal to zero Returns: list: with the missing numbers. @@ -27,14 +27,14 @@ def missing_number(nums: list, n: int) -> int: AssertionError: if one of the arguments is invalid. Examples: - >>> missing_number([0,2], 3) - [1] - >>> missing_number([0,1,3], 5) - [2,4] + >>> missing_number([0, 2], 3) + [1, 3] + >>> missing_number([0, 1, 3], 5) + [2, 4, 5] """ - # the nums length should be an integer greater than 0 - assert n >= 0, "n must be greater than or equal to zero" + + assert n >= 0 full_set = set(range(n + 1)) # The expected set of numbers is from 0 to n @@ -43,6 +43,5 @@ def missing_number(nums: list, n: int) -> int: # The actual set of numbers present in the 'nums' list missing = list(full_set - nums_set) - # The missing numbers are the difference between the full set and the actual set return missing diff --git a/solutions/tests/test_missing_number.py b/solutions/tests/test_missing_number.py index 352a5d390..df7aa6b66 100644 --- a/solutions/tests/test_missing_number.py +++ b/solutions/tests/test_missing_number.py @@ -1,57 +1,66 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +""" + +Test module for missing_number function. +Checks with numbers are missed out of a sequence. + +Test categories: + - Standard cases: only one missing value. + - Edge cases: empty list and list with one number. + - Defensive tests: invalid inputs or duplicate values. + + Created on 2025-01-04 + Author: Alaa Mohamed + +""" + import unittest from ..missing_number import missing_number class TestMissingNumber(unittest.TestCase): - """ - Test module for missing_number function. - Checks with numbers are missed out of a sequence. - - Test categories: - - Standard cases: only one missing value. - - Edge cases: empty list and list with one number. - - Defensive tests: invalid inputs or duplicate values. - - Created on 2025-01-04 - Author: Alaa Mohamed - """ + """ Test case for missing_number foundation """ -def test_only_one_missing_number(self): - "The list is [0, 1, 3] and n is 3" - "Missing number should be [2]" - self.assertEqual(missing_number([0, 1, 3], 3), [2]) + def test_only_one_missing_number(self): + """The list is [0, 1, 3] and n is 3" + Missing number should be [2]""" + self.assertEqual(missing_number([0, 1, 3], 3), [2]) -def test_an_empty_list(self): - "The list is [] and n is 0" - "Missing number should be [0]" - self.assertEqual(missing_number([], 0), [0]) + def test_an_empty_list(self): + """The list is [] and n is 0 + Missing number should be [0]""" + self.assertEqual(missing_number([], 0), [0]) -def test_list_with_one_number(self): - "The list is [0] and n is 1" - "Missing number should be [1]" - self.assertEqual(missing_number([0], 1), [1]) + def test_list_with_one_number(self): + """The list is [0] and n is 1 + Missing number should be [1]""" + self.assertEqual(missing_number([0], 1), [1]) -def test_with_two_missing_numbers(self): - "The list is [1, 3, 5] and n is 5" - "Missing number should be [2, 4]" - self.assertEqual(missing_number([1, 3, 5], 5), [0, 2, 4]) + def test_with_two_missing_numbers(self): + """The list is [1, 3, 5] and n is 5 + Missing number should be [2, 4]""" + self.assertEqual(missing_number([1, 3, 5], 5), [0, 2, 4]) -def test_list_with_no_missing_number(self): - "The list is [0, 1, 2] and n is 2" - "Missing number should be []" - self.assertEqual(missing_number([0, 1, 2], 2), []) + def test_list_with_no_missing_number(self): + """The list is [0, 1, 2] and n is 2 + Missing number should be []""" + self.assertEqual(missing_number([0, 1, 2], 2), []) -def test_duplicate_numbers(self): - "The list is [0, 1, 2, 2, 3, 4] and n is 4" - "Missing number should be []" - self.assertEqual(missing_number([0, 1, 2, 2, 3, 4], 4), []) + def test_duplicate_numbers(self): + """The list is [0, 1, 2, 2, 3, 4] and n is 4 + Missing number should be []""" + self.assertEqual(missing_number([0, 1, 2, 2, 3, 4], 4), []) + + def test_invalid_input(self): + """It should raise an assertion error if the input is invalid.""" + with self.assertRaises(AssertionError): + missing_number([], 1.5) \ No newline at end of file From c884fc435fdadaeed73902f446947a328e0126de Mon Sep 17 00:00:00 2001 From: Alaa Date: Mon, 6 Jan 2025 20:38:40 +0200 Subject: [PATCH 27/48] code will not pass py tests as an error will occur in the case of invalid inputs --- solutions/tests/test_missing_number.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/tests/test_missing_number.py b/solutions/tests/test_missing_number.py index df7aa6b66..491e30f25 100644 --- a/solutions/tests/test_missing_number.py +++ b/solutions/tests/test_missing_number.py @@ -26,7 +26,7 @@ class TestMissingNumber(unittest.TestCase): def test_only_one_missing_number(self): - """The list is [0, 1, 3] and n is 3" + """The list is [0, 1, 3] and n is 3 Missing number should be [2]""" self.assertEqual(missing_number([0, 1, 3], 3), [2]) From 70e5dc55a791a43ccaeafb8d7d905e5c0a81857a Mon Sep 17 00:00:00 2001 From: Alaa Date: Mon, 6 Jan 2025 20:45:03 +0200 Subject: [PATCH 28/48] fixed formatting error --- solutions/tests/test_missing_number.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/solutions/tests/test_missing_number.py b/solutions/tests/test_missing_number.py index 491e30f25..2b5b391ef 100644 --- a/solutions/tests/test_missing_number.py +++ b/solutions/tests/test_missing_number.py @@ -10,10 +10,10 @@ - Standard cases: only one missing value. - Edge cases: empty list and list with one number. - Defensive tests: invalid inputs or duplicate values. - + Created on 2025-01-04 Author: Alaa Mohamed - + """ import unittest @@ -22,8 +22,7 @@ class TestMissingNumber(unittest.TestCase): - """ Test case for missing_number foundation """ - + """Test case for missing_number foundation""" def test_only_one_missing_number(self): """The list is [0, 1, 3] and n is 3 @@ -35,7 +34,7 @@ def test_an_empty_list(self): """The list is [] and n is 0 Missing number should be [0]""" self.assertEqual(missing_number([], 0), [0]) - + def test_list_with_one_number(self): """The list is [0] and n is 1 @@ -47,20 +46,20 @@ def test_with_two_missing_numbers(self): """The list is [1, 3, 5] and n is 5 Missing number should be [2, 4]""" self.assertEqual(missing_number([1, 3, 5], 5), [0, 2, 4]) - + def test_list_with_no_missing_number(self): """The list is [0, 1, 2] and n is 2 Missing number should be []""" self.assertEqual(missing_number([0, 1, 2], 2), []) - + def test_duplicate_numbers(self): """The list is [0, 1, 2, 2, 3, 4] and n is 4 Missing number should be []""" self.assertEqual(missing_number([0, 1, 2, 2, 3, 4], 4), []) - + def test_invalid_input(self): """It should raise an assertion error if the input is invalid.""" with self.assertRaises(AssertionError): - missing_number([], 1.5) \ No newline at end of file + missing_number([], 1.5) From 967c0a1de0989c3ce989112e7c071d06bd1ef70a Mon Sep 17 00:00:00 2001 From: Alaa Date: Mon, 6 Jan 2025 20:59:15 +0200 Subject: [PATCH 29/48] edited formatting errors --- solutions/tests/test_missing_number.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solutions/tests/test_missing_number.py b/solutions/tests/test_missing_number.py index 2b5b391ef..fd79ecba3 100644 --- a/solutions/tests/test_missing_number.py +++ b/solutions/tests/test_missing_number.py @@ -34,7 +34,7 @@ def test_an_empty_list(self): """The list is [] and n is 0 Missing number should be [0]""" self.assertEqual(missing_number([], 0), [0]) - + def test_list_with_one_number(self): """The list is [0] and n is 1 @@ -46,13 +46,13 @@ def test_with_two_missing_numbers(self): """The list is [1, 3, 5] and n is 5 Missing number should be [2, 4]""" self.assertEqual(missing_number([1, 3, 5], 5), [0, 2, 4]) - + def test_list_with_no_missing_number(self): """The list is [0, 1, 2] and n is 2 Missing number should be []""" self.assertEqual(missing_number([0, 1, 2], 2), []) - + def test_duplicate_numbers(self): """The list is [0, 1, 2, 2, 3, 4] and n is 4 From 5d8272cc0dfabcffa0068cff7305912f1a8bbbca Mon Sep 17 00:00:00 2001 From: Alaa Date: Mon, 6 Jan 2025 21:14:05 +0200 Subject: [PATCH 30/48] trying again with formatting error --- solutions/tests/test_missing_number.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/solutions/tests/test_missing_number.py b/solutions/tests/test_missing_number.py index fd79ecba3..f054ab8de 100644 --- a/solutions/tests/test_missing_number.py +++ b/solutions/tests/test_missing_number.py @@ -29,31 +29,26 @@ def test_only_one_missing_number(self): Missing number should be [2]""" self.assertEqual(missing_number([0, 1, 3], 3), [2]) - def test_an_empty_list(self): """The list is [] and n is 0 Missing number should be [0]""" self.assertEqual(missing_number([], 0), [0]) - def test_list_with_one_number(self): """The list is [0] and n is 1 Missing number should be [1]""" self.assertEqual(missing_number([0], 1), [1]) - def test_with_two_missing_numbers(self): """The list is [1, 3, 5] and n is 5 Missing number should be [2, 4]""" self.assertEqual(missing_number([1, 3, 5], 5), [0, 2, 4]) - def test_list_with_no_missing_number(self): """The list is [0, 1, 2] and n is 2 Missing number should be []""" self.assertEqual(missing_number([0, 1, 2], 2), []) - def test_duplicate_numbers(self): """The list is [0, 1, 2, 2, 3, 4] and n is 4 Missing number should be []""" From dd0bab6ed47504f5cd30b36e6bdf2bf1ea35b185 Mon Sep 17 00:00:00 2001 From: Alaa Date: Mon, 6 Jan 2025 21:22:23 +0200 Subject: [PATCH 31/48] add an assertion to pass through the py tests --- solutions/missing_number.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/missing_number.py b/solutions/missing_number.py index e94f20ab1..6ba74260b 100644 --- a/solutions/missing_number.py +++ b/solutions/missing_number.py @@ -33,7 +33,7 @@ def missing_number(nums: list, n: int) -> int: [2, 4, 5] """ - + assert isinstance(n, int) assert n >= 0 full_set = set(range(n + 1)) From d34c8755b1ab8c1953ed7d55af8240ec593ff2b8 Mon Sep 17 00:00:00 2001 From: Dr-Amin-K Date: Tue, 7 Jan 2025 06:02:48 +0400 Subject: [PATCH 32/48] Done missing numbers challenge and its test file --- solutions/missing_numbers.py | 60 +++++++++++++++++++++++ solutions/tests/test_missing_numbers.py | 63 +++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 solutions/missing_numbers.py create mode 100644 solutions/tests/test_missing_numbers.py diff --git a/solutions/missing_numbers.py b/solutions/missing_numbers.py new file mode 100644 index 000000000..9e3173d95 --- /dev/null +++ b/solutions/missing_numbers.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module that returns a sorted list of all the missing numbers in a string containing integers separated by spaces. + +Module contents: + - missing_numbers: creates a list with all the missing integers. + +Created on 06/01/2025 +@author: Amin +""" + + +def missing_numbers(nums_string: str) -> list: + """Find the missing numbers in a list of integers. + + Parameters: + nums_string: string, the input string containing the integers to be checked + + Returns -> list: the list of the missing integers in the input string + Raises: + AssertionError: if the argument is not a list of integers + >>> missing_numbers("0 1") + [] + >>> missing_numbers("0 2 3") + [1] + >>> missing_numbers("0 4") + [1, 2, 3] + >>> missing_numbers("3 1 7") + [2, 4, 5, 6] + """ + assert isinstance( + nums_string, str + ), "input must be a string containing integers separated by spaces" + # Transform the original numbers string into a list by splitting it + nums_list = nums_string.split() + nums = [] + # Transform each element of the list from str into an integer + for i in nums_list: + try: + num = int(i) + nums.append(num) + + except: + return "The input contains non-integer values" + miss = [] + # Identify the maximal number in the list + maximum = nums[0] + for i in nums: + if i > maximum: + maximum = i + # Identify the minimal number in the list + minimum = nums[0] + for i in nums: + if i < minimum: + minimum = i + for num in range(minimum + 1, maximum): + if num not in nums: + miss.append(num) + return miss diff --git a/solutions/tests/test_missing_numbers.py b/solutions/tests/test_missing_numbers.py new file mode 100644 index 000000000..79bb50c91 --- /dev/null +++ b/solutions/tests/test_missing_numbers.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for testing the missing_numbers function. + +Test cases include: + - strings with missing numbers. + - strings without missing numbers. + - strings containing letters or other non-numerical characters. + - strings containing number formats other than integers. + - strings containing different spacing sizes. + - Sorted and unsorted numbers. + - Edge cases: empty strings, single-number strings. + - Invalid inputs: non-string values (e.g., integers or floats). + +Created on 06/01/2025 +@author: Amin +""" + +import unittest + +from ..missing_numbers import missing_numbers + + +class TestMissingNumbers(unittest.TestCase): + """Test the missing_number function""" + + def test_unsorted_string(self): + """It should return a sorted list with all the missing numbers""" + self.assertEqual(missing_numbers("3 0"), [1, 2]) + + def test_no_missing_number(self): + """It should return [] for lists without missing numbers""" + self.assertEqual(missing_numbers("1 2"), []) + + def test_one_missing_number(self): + """It should return a list containing only the missing number""" + self.assertEqual(missing_numbers("0 2"), [1]) + + def test_multiple_cases(self): + """It should return a sorted list with all the missing numbers""" + self.assertEqual(missing_numbers("1 4"), [2, 3]) + + def test_different_spaces(self): + """It should function properly regardless of how many spaces are there in the initial string""" + self.assertEqual(missing_numbers("1 4"), [2, 3]) + + def test_not_string(self): + """It should raise AssertionError for non-string input""" + with self.assertRaises(AssertionError): + missing_numbers(123) + + def test_not_numbers(self): + """It should return a message for strings containing letters or other non-numerical characters""" + self.assertEqual( + missing_numbers("1 g"), ("The input contains non-integer values") + ) + + def test_non_integer_numbers(self): + """It should return a message for strings containing number formats other than integers""" + self.assertEqual( + missing_numbers("1 2.1"), ("The input contains non-integer values") + ) From c4e01bf8ffc38901b0255f0afaa02b4376662f69 Mon Sep 17 00:00:00 2001 From: Alaa Date: Tue, 7 Jan 2025 12:47:31 +0200 Subject: [PATCH 33/48] added a third example --- solutions/missing_number.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/solutions/missing_number.py b/solutions/missing_number.py index 6ba74260b..386100103 100644 --- a/solutions/missing_number.py +++ b/solutions/missing_number.py @@ -31,6 +31,8 @@ def missing_number(nums: list, n: int) -> int: [1, 3] >>> missing_number([0, 1, 3], 5) [2, 4, 5] + >>> missing_number([0, 2], 2) + [1] """ assert isinstance(n, int) From fb3cb760d4d22b5bc0791f21d05848f133f3aa7e Mon Sep 17 00:00:00 2001 From: Mohamed Saeed <99553124+Tbaosman@users.noreply.github.com> Date: Wed, 8 Jan 2025 16:23:06 +0400 Subject: [PATCH 34/48] Revert "Done missing numbers challenge and its test file" --- solutions/missing_numbers.py | 60 ----------------------- solutions/tests/test_missing_numbers.py | 63 ------------------------- 2 files changed, 123 deletions(-) delete mode 100644 solutions/missing_numbers.py delete mode 100644 solutions/tests/test_missing_numbers.py diff --git a/solutions/missing_numbers.py b/solutions/missing_numbers.py deleted file mode 100644 index 9e3173d95..000000000 --- a/solutions/missing_numbers.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -A module that returns a sorted list of all the missing numbers in a string containing integers separated by spaces. - -Module contents: - - missing_numbers: creates a list with all the missing integers. - -Created on 06/01/2025 -@author: Amin -""" - - -def missing_numbers(nums_string: str) -> list: - """Find the missing numbers in a list of integers. - - Parameters: - nums_string: string, the input string containing the integers to be checked - - Returns -> list: the list of the missing integers in the input string - Raises: - AssertionError: if the argument is not a list of integers - >>> missing_numbers("0 1") - [] - >>> missing_numbers("0 2 3") - [1] - >>> missing_numbers("0 4") - [1, 2, 3] - >>> missing_numbers("3 1 7") - [2, 4, 5, 6] - """ - assert isinstance( - nums_string, str - ), "input must be a string containing integers separated by spaces" - # Transform the original numbers string into a list by splitting it - nums_list = nums_string.split() - nums = [] - # Transform each element of the list from str into an integer - for i in nums_list: - try: - num = int(i) - nums.append(num) - - except: - return "The input contains non-integer values" - miss = [] - # Identify the maximal number in the list - maximum = nums[0] - for i in nums: - if i > maximum: - maximum = i - # Identify the minimal number in the list - minimum = nums[0] - for i in nums: - if i < minimum: - minimum = i - for num in range(minimum + 1, maximum): - if num not in nums: - miss.append(num) - return miss diff --git a/solutions/tests/test_missing_numbers.py b/solutions/tests/test_missing_numbers.py deleted file mode 100644 index 79bb50c91..000000000 --- a/solutions/tests/test_missing_numbers.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -A module for testing the missing_numbers function. - -Test cases include: - - strings with missing numbers. - - strings without missing numbers. - - strings containing letters or other non-numerical characters. - - strings containing number formats other than integers. - - strings containing different spacing sizes. - - Sorted and unsorted numbers. - - Edge cases: empty strings, single-number strings. - - Invalid inputs: non-string values (e.g., integers or floats). - -Created on 06/01/2025 -@author: Amin -""" - -import unittest - -from ..missing_numbers import missing_numbers - - -class TestMissingNumbers(unittest.TestCase): - """Test the missing_number function""" - - def test_unsorted_string(self): - """It should return a sorted list with all the missing numbers""" - self.assertEqual(missing_numbers("3 0"), [1, 2]) - - def test_no_missing_number(self): - """It should return [] for lists without missing numbers""" - self.assertEqual(missing_numbers("1 2"), []) - - def test_one_missing_number(self): - """It should return a list containing only the missing number""" - self.assertEqual(missing_numbers("0 2"), [1]) - - def test_multiple_cases(self): - """It should return a sorted list with all the missing numbers""" - self.assertEqual(missing_numbers("1 4"), [2, 3]) - - def test_different_spaces(self): - """It should function properly regardless of how many spaces are there in the initial string""" - self.assertEqual(missing_numbers("1 4"), [2, 3]) - - def test_not_string(self): - """It should raise AssertionError for non-string input""" - with self.assertRaises(AssertionError): - missing_numbers(123) - - def test_not_numbers(self): - """It should return a message for strings containing letters or other non-numerical characters""" - self.assertEqual( - missing_numbers("1 g"), ("The input contains non-integer values") - ) - - def test_non_integer_numbers(self): - """It should return a message for strings containing number formats other than integers""" - self.assertEqual( - missing_numbers("1 2.1"), ("The input contains non-integer values") - ) From 367365ef5a00183bd841ba4580a110e23c5d00d8 Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 8 Jan 2025 18:14:05 +0400 Subject: [PATCH 35/48] Completed the max integer challenge --- solutions/max_integer.py | 47 +++++++++++++++++++ solutions/tests/test_max_integer.py | 72 +++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 solutions/max_integer.py create mode 100644 solutions/tests/test_max_integer.py diff --git a/solutions/max_integer.py b/solutions/max_integer.py new file mode 100644 index 000000000..eb48af07d --- /dev/null +++ b/solutions/max_integer.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for obtaining max integer from a list. + +Module contents: + - max_integer: Returns maximum integer from a list of integers + +Created on 2025-01-08 +Author: Tamir Elwaleeed +""" + + +def max_integer(my_list: list) -> int: + """Returns the max integer in a list of integers + If the list is empty, the function returns None + + Parameters: + my_list: list, the list to find the max from + + Returns -> int: the max integer from the list + + Raises: + AssertionError: if input is not a list + AssertionError: if one of the elements isn't a number + + Examples: + >>> max_integer([1, 2, 3, 4, 5]) + 5 + >>> max_integer([-1, -4, -5]) + -1 + >>> max_integer([]) + None + """ + assert isinstance(my_list, list), "input must be a list" + for i in my_list: + assert isinstance(i, int), "elements must be numbers" + + if len(my_list) == 0: + return None + result = my_list[0] + i = 1 + while i < len(my_list): + if my_list[i] > result: + result = my_list[i] + i += 1 + return result \ No newline at end of file diff --git a/solutions/tests/test_max_integer.py b/solutions/tests/test_max_integer.py new file mode 100644 index 000000000..1d17bca07 --- /dev/null +++ b/solutions/tests/test_max_integer.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Test module for max_integer function. + +Test categories: + - Standard cases: typical lists with different lengths + - Edge cases: empty lists, single elements, strings + - Defensive tests: wrong input types, assertions + +Created on 2025-01-08 +Author: Tamir Elwaleeed +""" + +import unittest +from ..max_integer import max_integer + + +class TestMaxInteger(unittest.TestCase): + """Define unittests for max_integer([..]).""" + + def test_ordered_list(self): + """Test an ordered list of integers.""" + ordered = [1, 2, 3, 4] + self.assertEqual(max_integer(ordered), 4) + + def test_unordered_list(self): + """Test an unordered list of integers.""" + unordered = [1, 2, 4, 3] + self.assertEqual(max_integer(unordered), 4) + + def test_max_at_begginning(self): + """Test a list with a beginning max value.""" + max_at_beginning = [4, 3, 2, 1] + self.assertEqual(max_integer(max_at_beginning), 4) + + def test_empty_list(self): + """Test an empty list.""" + empty = [] + self.assertEqual(max_integer(empty), None) + + def test_one_element_list(self): + """Test a list with a single element.""" + one_element = [7] + self.assertEqual(max_integer(one_element), 7) + + def test_floats(self): + """Test a list of floats.""" + floats = [1.53, 6.33, -9.123, 15.2, 6.0] + self.assertEqual(max_integer(floats), 15.2) + + def test_ints_and_floats(self): + """Test a list of ints and floats.""" + ints_and_floats = [1.53, 15.5, -9, 15, 6] + self.assertEqual(max_integer(ints_and_floats), 15.5) + + def test_string(self): + """Test a string.""" + string = "Brennan" + self.assertEqual(max_integer(string), 'r') + + def test_list_of_strings(self): + """Test a list of strings.""" + strings = ["Brennan", "is", "my", "name"] + self.assertEqual(max_integer(strings), "name") + + def test_empty_string(self): + """Test an empty string.""" + self.assertEqual(max_integer(""), None) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From d5f09367ef796091ad619946c5f2a5fa8538949e Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 8 Jan 2025 18:35:16 +0400 Subject: [PATCH 36/48] Fixed tests and formatting --- solutions/max_integer.py | 16 ++++++++-------- solutions/tests/test_max_integer.py | 14 +++++++++----- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/solutions/max_integer.py b/solutions/max_integer.py index eb48af07d..b6a849501 100644 --- a/solutions/max_integer.py +++ b/solutions/max_integer.py @@ -14,16 +14,16 @@ def max_integer(my_list: list) -> int: """Returns the max integer in a list of integers If the list is empty, the function returns None - + Parameters: my_list: list, the list to find the max from - + Returns -> int: the max integer from the list - + Raises: AssertionError: if input is not a list AssertionError: if one of the elements isn't a number - + Examples: >>> max_integer([1, 2, 3, 4, 5]) 5 @@ -31,11 +31,11 @@ def max_integer(my_list: list) -> int: -1 >>> max_integer([]) None - """ + """ assert isinstance(my_list, list), "input must be a list" for i in my_list: - assert isinstance(i, int), "elements must be numbers" - + assert isinstance(i, float), "elements must be numbers" + if len(my_list) == 0: return None result = my_list[0] @@ -44,4 +44,4 @@ def max_integer(my_list: list) -> int: if my_list[i] > result: result = my_list[i] i += 1 - return result \ No newline at end of file + return result diff --git a/solutions/tests/test_max_integer.py b/solutions/tests/test_max_integer.py index 1d17bca07..1dd5f788d 100644 --- a/solutions/tests/test_max_integer.py +++ b/solutions/tests/test_max_integer.py @@ -57,16 +57,20 @@ def test_ints_and_floats(self): def test_string(self): """Test a string.""" string = "Brennan" - self.assertEqual(max_integer(string), 'r') + with self.assertRaises(AssertionError): + max_integer(string) def test_list_of_strings(self): """Test a list of strings.""" strings = ["Brennan", "is", "my", "name"] - self.assertEqual(max_integer(strings), "name") + with self.assertRaises(AssertionError): + max_integer(strings) def test_empty_string(self): """Test an empty string.""" - self.assertEqual(max_integer(""), None) + with self.assertRaises(AssertionError): + max_integer("") -if __name__ == '__main__': - unittest.main() \ No newline at end of file + +if __name__ == "__main__": + unittest.main() From 02bd25a6571d8b15c2db7ca46ae86595c10e80bf Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 8 Jan 2025 18:39:21 +0400 Subject: [PATCH 37/48] Fixed tests --- solutions/max_integer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/max_integer.py b/solutions/max_integer.py index b6a849501..eee14b581 100644 --- a/solutions/max_integer.py +++ b/solutions/max_integer.py @@ -34,7 +34,7 @@ def max_integer(my_list: list) -> int: """ assert isinstance(my_list, list), "input must be a list" for i in my_list: - assert isinstance(i, float), "elements must be numbers" + assert isinstance(i, float or int), "elements must be numbers" if len(my_list) == 0: return None From 5e5c079a3e3cba545b4d8657be6314dabf462e88 Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 8 Jan 2025 18:42:48 +0400 Subject: [PATCH 38/48] Fixed tests --- solutions/max_integer.py | 2 -- solutions/tests/test_max_integer.py | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/solutions/max_integer.py b/solutions/max_integer.py index eee14b581..e21b3af1d 100644 --- a/solutions/max_integer.py +++ b/solutions/max_integer.py @@ -33,8 +33,6 @@ def max_integer(my_list: list) -> int: None """ assert isinstance(my_list, list), "input must be a list" - for i in my_list: - assert isinstance(i, float or int), "elements must be numbers" if len(my_list) == 0: return None diff --git a/solutions/tests/test_max_integer.py b/solutions/tests/test_max_integer.py index 1dd5f788d..3c8c88bd9 100644 --- a/solutions/tests/test_max_integer.py +++ b/solutions/tests/test_max_integer.py @@ -57,14 +57,12 @@ def test_ints_and_floats(self): def test_string(self): """Test a string.""" string = "Brennan" - with self.assertRaises(AssertionError): - max_integer(string) + self.assertEqual(max_integer(string), "r") def test_list_of_strings(self): """Test a list of strings.""" strings = ["Brennan", "is", "my", "name"] - with self.assertRaises(AssertionError): - max_integer(strings) + self.assertEqual(max_integer(strings), "name") def test_empty_string(self): """Test an empty string.""" From 3548a3279b2e9bc972d8caa4efeb59f1a641e12c Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 8 Jan 2025 18:45:18 +0400 Subject: [PATCH 39/48] Fixed tests --- solutions/tests/test_max_integer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solutions/tests/test_max_integer.py b/solutions/tests/test_max_integer.py index 3c8c88bd9..7720d6b02 100644 --- a/solutions/tests/test_max_integer.py +++ b/solutions/tests/test_max_integer.py @@ -57,7 +57,8 @@ def test_ints_and_floats(self): def test_string(self): """Test a string.""" string = "Brennan" - self.assertEqual(max_integer(string), "r") + with self.assertRaises(AssertionError): + max_integer(string) def test_list_of_strings(self): """Test a list of strings.""" From 48b69ebeb37b567181c610b1978b06c1975bac57 Mon Sep 17 00:00:00 2001 From: kefahalshaer Date: Wed, 8 Jan 2025 17:32:19 +0200 Subject: [PATCH 40/48] update base readme file --- README.md | 117 ++++++-------------------------- collaboration/learning_goals.md | 6 ++ 2 files changed, 27 insertions(+), 96 deletions(-) diff --git a/README.md b/README.md index 33aa84163..e3cd496a7 100644 --- a/README.md +++ b/README.md @@ -1,105 +1,30 @@ -# 👋 Welcome: This is `PyRectifier` Group +# 👋 Welcome: This is ⚡`PyRectifiers`⚡Group -## We made this repository to practice what we learn in the `MIT Foundational Track` - -### The most important points that we are as a team individuals practicing here - -1. To master using GitHub & Git. (msaeed) -2. To foster my programming skills. (msaeed) -3. To learn how to work collaboratively within groups and organizations by - learning and practicing the best practices and approaches. (msaeed) -4. To understand how to plan and execute projects on Github. (Amin) -5. To transform my ideas into programs (Amin) -6. Write unit test files. (Kefah) -7. Practicing Review code. (Kefah) -8. ... (Colleagues: Add what you're thinking about) - -### Learning Goals - - Our learning goals are categorized into two main areas: Focus on `Collective - Goals`, that is improving together as a team, and `Individual Goals`, that - focus on helping individual areas of growth based on the aspirations of each - member. This structured approach guarantees both group development and - personal development. - -### 1. Collective Learning Goals - - Together, we seek to build a collaborative development environment where - we sharpen our technical and communication skills. With practice and - continuous learning, we’ll develop a strong foundation in software - development and Python programming. The following will be our key points - as a collective to learn together. - -#### 1. Collaborative Development Skills - -- Develop effective collaboration practices through GitHub workflows, including: - - **Issues**: Creating, tracking, and assigning tasks. - - **Pull Requests (PRs)**: Submitting, reviewing, and merging pull requests - to ensure code quality. - - **Merging**: Understanding different merge strategies and resolving conflicts. - - **Projects**: Organizing tasks and milestones using GitHub Projects for - visual tracking. - - **Branching**: Managing branches effectively to keep the repository clean - and organized. - - **GitHub CLI**: Managing repositories, pull requests, and issues from the terminal. - -#### 2. Effective Communication - -- Enhance communication skills within the team through: - - **Slack**: Using Slack for group communication. - - **Regular Meetings**: Actively participate in group meetings and - discussions to ensure alignment on goals and progress. - - **Feedback and Collaboration**: Providing and receiving constructive - feedback in both code reviews and team discussions. - -#### 3. Unit Testing +🚀 **"Alone we can do so little; together, we can achieve so much."** -- Learn and integrate unit testing in Python using the unittest module. - -#### 4. Code Review Process - -- Develop an understanding of an effective code review process, giving and - receiving constructive feedback to improve code quality. - -#### 5. Efficient Development Practices - -- Focus on becoming more efficient developers by improving workflows - debugging techniques, and programming skills. - -#### 6. Python Programming - -- Strengthen Python programming skills by: - - Writing efficient, and well-documented Python code. - -#### 7. Docstring Documentation - -- Learn the art of writing. - -### 2. Individual Learning Goals - -#### **Alexander Andom** - - 1. Learn New Data Structures: - - Learn and implement new data structures that are unfamiliar or challenging. - 2. Improve Debugging Skills: - - Develop strategies for debugging code and resolving issues more efficiently. - 3. Deepen Knowledge of Testing Frameworks: - - Learn to use unittest in Python to write solid and detailed unit tests. +## We made this repository to practice what we learn in the `MIT Foundational Track` -#### **Mohamed Saed** +``` text +💡 Our Vision: +To collaborate, innovate, and deliver impactful solutions. +This repository serves as our central hub for all documentation, +project discussions, and code contributions. +``` -- Mastering GitHub -- To foster my programming skills +### ⭐ Key Objectives -#### **Amin Abd Elraheem** +* Contribute meaningful 2 challenges at least, and review peers' +code for continuous improvements. -- To understand how to plan and execute projects on Github. -- To transform my ideas into programs. +### 📂 Repository Structure -#### **Kefah Albashityalshaer** +* **`main`**: The primary branch containing stable and reviewed code. +* **`collaboration/`**: Contain our group's learning goals, constrains, and + scheduling our team's meeting. +* **`notes/`**: Project's and team's notes. +* **`solutions/`**: Python solutions and corresponding test files for coding challenges. -- Improve my programming skills in Python, especially in writing unit test programs -- Mastering Code Review, making PRs, and the other GitHub teams' tasks. -- Improve team's communication. +### ✨ Our Journey ---- For the rest team's members, please add yours in the [doc here](https://docs.google.com/document/d/1A2wzylXGlXTTitTcOhgHJp50BXqLRtqdoCEJ2TlCaM0/edit?tab=t.0) +Our team's key insights, learnings, and collaborative decision-making processes: +Documented all in [`collaboration/`](https://github.com/MIT-Emerging-Talent/ET6-foundations-group-25/tree/main/collaboration) diff --git a/collaboration/learning_goals.md b/collaboration/learning_goals.md index d911159b4..051b3c3b3 100644 --- a/collaboration/learning_goals.md +++ b/collaboration/learning_goals.md @@ -79,3 +79,9 @@ to write solid and detailed unit tests. - To Understand how to plan and execute projects on GitHub. - Transform Ideas into Programs + +### *Kefah Albashityalshaer* + +- Improve my programming skills in Python, especially in writing unit test programs +- Mastering Code Review, making PRs, and the other GitHub teams' tasks. +- Improve my communication with the team. From 0a8a3c144f84a05da99a5838cc5de5cfefaa6fe3 Mon Sep 17 00:00:00 2001 From: Tamir Date: Thu, 9 Jan 2025 15:31:51 +0400 Subject: [PATCH 41/48] Added my learning goals, completed the min integer challenge --- collaboration/learning_goals.md | 6 +++ solutions/min_integer.py | 44 +++++++++++++++++ solutions/tests/test_min_integer.py | 75 +++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 solutions/min_integer.py create mode 100644 solutions/tests/test_min_integer.py diff --git a/collaboration/learning_goals.md b/collaboration/learning_goals.md index 051b3c3b3..eff08ad7d 100644 --- a/collaboration/learning_goals.md +++ b/collaboration/learning_goals.md @@ -85,3 +85,9 @@ to write solid and detailed unit tests. - Improve my programming skills in Python, especially in writing unit test programs - Mastering Code Review, making PRs, and the other GitHub teams' tasks. - Improve my communication with the team. + +### *Tamir El-Waleed* + +- Improve my testing skills, in addition to mastering basic Git & Github behavior. +- Create a complete project from scratch, building my portfolio in the process. + \ No newline at end of file diff --git a/solutions/min_integer.py b/solutions/min_integer.py new file mode 100644 index 000000000..ca6a8f5b4 --- /dev/null +++ b/solutions/min_integer.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for obtaining min integer from a list. + +Module contents: + - min_integer: Returns minimum integer from a list of integers + +Created on 2025-01-09 +Author: Tamir Elwaleeed +""" + + +def min_integer(my_list: list) -> int: + """Returns the min integer in a list of integers + If the list is empty, the function returns None + + Parameters: + my_list: list, the list to find the min from + + Returns -> int: the min integer from the list + + Raises: + AssertionError: if input is not a list + + Examples: + >>> min_integer([1, 2, 3, 4, 5]) + 1 + >>> min_integer([-1, -4, -5]) + -5 + >>> min_integer([]) + None + """ + assert isinstance(my_list, list), "input must be a list" + + if len(my_list) == 0: + return None + result = my_list[0] + i = 1 + while i < len(my_list): + if my_list[i] < result: + result = my_list[i] + i += 1 + return result \ No newline at end of file diff --git a/solutions/tests/test_min_integer.py b/solutions/tests/test_min_integer.py new file mode 100644 index 000000000..4b1f817ad --- /dev/null +++ b/solutions/tests/test_min_integer.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Test module for min_integer function. + +Test categories: + - Standard cases: typical lists with different lengths + - Edge cases: empty lists, single elements, strings + - Defensive tests: wrong input types, assertions + +Created on 2025-01-09 +Author: Tamir Elwaleeed +""" + +import unittest +from ..min_integer import min_integer + + +class TestminInteger(unittest.TestCase): + """Define unittests for min_integer([..]).""" + + def test_ordered_list(self): + """Test an ordered list of integers.""" + ordered = [1, 2, 3, 4] + self.assertEqual(min_integer(ordered), 1) + + def test_unordered_list(self): + """Test an unordered list of integers.""" + unordered = [1, 2, 4, 3] + self.assertEqual(min_integer(unordered), 1) + + def test_min_at_begginning(self): + """Test a list with a beginning min value.""" + min_at_beginning = [1, 4, 3, 2] + self.assertEqual(min_integer(min_at_beginning), 1) + + def test_empty_list(self): + """Test an empty list.""" + empty = [] + self.assertEqual(min_integer(empty), None) + + def test_one_element_list(self): + """Test a list with a single element.""" + one_element = [7] + self.assertEqual(min_integer(one_element), 7) + + def test_floats(self): + """Test a list of floats.""" + floats = [1.53, 6.33, -9.123, 15.2, 6.0] + self.assertEqual(min_integer(floats), -9.123) + + def test_ints_and_floats(self): + """Test a list of ints and floats.""" + ints_and_floats = [1.53, 15.5, -9, 15, 6] + self.assertEqual(min_integer(ints_and_floats), -9) + + def test_string(self): + """Test a string.""" + string = "Brennan" + with self.assertRaises(AssertionError): + min_integer(string) + + def test_list_of_strings(self): + """Test a list of strings.""" + strings = ["Brennan", "is", "my", "name"] + self.assertEqual(min_integer(strings), "Brennan") + + def test_empty_string(self): + """Test an empty string.""" + with self.assertRaises(AssertionError): + min_integer("") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From 55c6cbf9e864ac3879013b8a88e68e65d4838e12 Mon Sep 17 00:00:00 2001 From: Tamir Date: Thu, 9 Jan 2025 15:40:35 +0400 Subject: [PATCH 42/48] Fixed formatting --- solutions/min_integer.py | 2 +- solutions/tests/test_min_integer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solutions/min_integer.py b/solutions/min_integer.py index ca6a8f5b4..9c8fda491 100644 --- a/solutions/min_integer.py +++ b/solutions/min_integer.py @@ -41,4 +41,4 @@ def min_integer(my_list: list) -> int: if my_list[i] < result: result = my_list[i] i += 1 - return result \ No newline at end of file + return result diff --git a/solutions/tests/test_min_integer.py b/solutions/tests/test_min_integer.py index 4b1f817ad..2b9212707 100644 --- a/solutions/tests/test_min_integer.py +++ b/solutions/tests/test_min_integer.py @@ -72,4 +72,4 @@ def test_empty_string(self): if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() From 94cf13196cc2c54b0fc238c790057810c20a3f7a Mon Sep 17 00:00:00 2001 From: Tbaosman <99553124+Tbaosman@users.noreply.github.com.> Date: Fri, 10 Jan 2025 14:46:21 +0400 Subject: [PATCH 43/48] Fix formatting issues caused by an update --- solutions/is_leap_year.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solutions/is_leap_year.py b/solutions/is_leap_year.py index 50dfc5cd9..584599079 100644 --- a/solutions/is_leap_year.py +++ b/solutions/is_leap_year.py @@ -41,8 +41,8 @@ def is_leap_year(year: int) -> bool: """ assert isinstance(year, int), "year must be an integer" - assert ( - year >= 1583 - ), "year must be greater than or equal to 1583 (1582 is start of Gregorian Calendar)" + assert year >= 1583, ( + "year must be greater than or equal to 1583 (1582 is start of Gregorian Calendar)" + ) return (year % 4 == 0) and (year % 100 != 0 or year % 400 == 0) From d43d24ee24fa020f81b2a59b4aab698fa693c9f2 Mon Sep 17 00:00:00 2001 From: Dr-Amin-K Date: Fri, 10 Jan 2025 18:53:37 +0400 Subject: [PATCH 44/48] Done missing numbers challenge and its test file --- solutions/missing_numbers2.py | 56 ++++++++++++++++++++++ solutions/tests/test_missing_numbers2.py | 61 ++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 solutions/missing_numbers2.py create mode 100644 solutions/tests/test_missing_numbers2.py diff --git a/solutions/missing_numbers2.py b/solutions/missing_numbers2.py new file mode 100644 index 000000000..42900ccb1 --- /dev/null +++ b/solutions/missing_numbers2.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module that returns a sorted list of the missing numbers in a string of integers + +Module contents: + - missing_numbers2: creates a list with all the missing integers. + +Created on 06/01/2025 +@author: Amin +""" + + +def missing_numbers2(nums_string: str) -> list: + """Find the missing numbers in a list of integers. + + Parameters: + nums_string: string, the input string containing the integers to be checked + + Returns -> list: the list of the missing integers in the input string + Raises: + AssertionError: if the argument is not a list of integers + >>> missing_numbers2("0 1") + [] + >>> missing_numbers2("0 2 3") + [1] + >>> missing_numbers2("0 4") + [1, 2, 3] + >>> missing_numbers2("3 1 7") + [2, 4, 5, 6] + """ + assert isinstance( + nums_string, str + ), "input must be a string containing integers separated by spaces" + # Transform the original numbers string into a list by splitting it + nums_list = nums_string.split() + nums = [] + # Transform each element of the list from str into an integer + for i in nums_list: + num = int(i) + nums.append(num) + miss = [] + # Identify the maximal number in the list + maximum = nums[0] + for i in nums: + if i > maximum: + maximum = i + # Identify the minimal number in the list + minimum = nums[0] + for i in nums: + if i < minimum: + minimum = i + for num in range(minimum + 1, maximum): + if num not in nums: + miss.append(num) + return miss diff --git a/solutions/tests/test_missing_numbers2.py b/solutions/tests/test_missing_numbers2.py new file mode 100644 index 000000000..104512812 --- /dev/null +++ b/solutions/tests/test_missing_numbers2.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for testing the missing_numbers function. + +Test cases include: + - strings with missing numbers. + - strings without missing numbers. + - strings containing letters or other non-numerical characters. + - strings containing number formats other than integers. + - strings containing different spacing sizes. + - Sorted and unsorted numbers. + - Edge cases: empty strings, single-number strings. + - Invalid inputs: non-string values (e.g., integers or floats). + +Created on 06/01/2025 +@author: Amin +""" + +import unittest + +from ..missing_numbers2 import missing_numbers2 + + +class TestMissingNumbers(unittest.TestCase): + """Test the missing_number function""" + + def test_unsorted_string(self): + """It should return a sorted list with all the missing numbers""" + self.assertEqual(missing_numbers2("3 0"), [1, 2]) + + def test_no_missing_number(self): + """It should return [] for lists without missing numbers""" + self.assertEqual(missing_numbers2("1 2"), []) + + def test_one_missing_number(self): + """It should return a list containing only the missing number""" + self.assertEqual(missing_numbers2("0 2"), [1]) + + def test_multiple_cases(self): + """It should return a sorted list with all the missing numbers""" + self.assertEqual(missing_numbers2("1 4"), [2, 3]) + + def test_different_spaces(self): + """It should function properly regardless of how many spaces are there in the string""" + self.assertEqual(missing_numbers2("1 4"), [2, 3]) + + def test_not_string(self): + """It should raise AssertionError for non-string input""" + with self.assertRaises(AssertionError): + missing_numbers2(123) + + def test_not_numbers(self): + """It should raise AssertionError for strings with letters or non-numerical characters""" + with self.assertRaises(ValueError): + missing_numbers2("1 g") + + def test_non_integer_numbers(self): + """It should raise AssertionError for strings containing numbers other than integers""" + with self.assertRaises(ValueError): + missing_numbers2("1 2.1") From a3f40bf3e5bfd7b5424e502fb574cc006dee3fa7 Mon Sep 17 00:00:00 2001 From: Dr-Amin-K Date: Fri, 10 Jan 2025 19:12:44 +0400 Subject: [PATCH 45/48] Done missing numbers challenge and its test file2 --- solutions/missing_numbers2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solutions/missing_numbers2.py b/solutions/missing_numbers2.py index 42900ccb1..8153b0025 100644 --- a/solutions/missing_numbers2.py +++ b/solutions/missing_numbers2.py @@ -29,9 +29,9 @@ def missing_numbers2(nums_string: str) -> list: >>> missing_numbers2("3 1 7") [2, 4, 5, 6] """ - assert isinstance( - nums_string, str - ), "input must be a string containing integers separated by spaces" + assert isinstance(nums_string, str), ( + "input must be a string containing integers separated by spaces" + ) # Transform the original numbers string into a list by splitting it nums_list = nums_string.split() nums = [] From b54bbf6581fc2aec417775ac0cee4fe2799f7b6b Mon Sep 17 00:00:00 2001 From: Tamir Date: Sun, 12 Jan 2025 15:57:07 +0400 Subject: [PATCH 46/48] Fixed PascalCase & Spelling Error --- solutions/tests/test_min_integer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solutions/tests/test_min_integer.py b/solutions/tests/test_min_integer.py index 2b9212707..0acfc4bc0 100644 --- a/solutions/tests/test_min_integer.py +++ b/solutions/tests/test_min_integer.py @@ -16,7 +16,7 @@ from ..min_integer import min_integer -class TestminInteger(unittest.TestCase): +class TestMinInteger(unittest.TestCase): """Define unittests for min_integer([..]).""" def test_ordered_list(self): @@ -29,7 +29,7 @@ def test_unordered_list(self): unordered = [1, 2, 4, 3] self.assertEqual(min_integer(unordered), 1) - def test_min_at_begginning(self): + def test_min_at_beginning(self): """Test a list with a beginning min value.""" min_at_beginning = [1, 4, 3, 2] self.assertEqual(min_integer(min_at_beginning), 1) From 4e3dd98c725222ff0870579ea84ea219c6c18a2c Mon Sep 17 00:00:00 2001 From: kefahalshaer Date: Sun, 12 Jan 2025 21:10:31 +0200 Subject: [PATCH 47/48] upload maximum_length.py challenge --- solutions/maximum_length.py | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 solutions/maximum_length.py diff --git a/solutions/maximum_length.py b/solutions/maximum_length.py new file mode 100644 index 000000000..5789a2f38 --- /dev/null +++ b/solutions/maximum_length.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module to find the maximum length of the +concatenation of a subsequence of arr that has unique characters. + +Return the maximum possible length of s + +Module contents: + - maxLength: Function to get the Maximum Length of a Concatenated String with Unique Characters + - backtrack: Helper function to perform backtracking + +Created on 2024-01-12 +Author: Kefah Albashityalshaer +""" + + +def max_length(arr: list) -> int: + """ + Function to get the Maximum Length of a Concatenated String with Unique Characters + + Takes a list of strings and returns the max length of concatenated string with unique characters + + Parameters: + arr: list of stings elements to process + + Returns -> int: the maximum length + + Examples: + >>> max_length(["un","iq","ue"]) + 4 + >>> max_length(["cha","r","act","ers"]) + 6 + >>> max_length(["abcdefghijklmnopqrstuvwxyz"]) + 26 + >>> max_length(["a", "bb", "ccc"]) + 1 + >>> max_length([]) + 0 + """ + assert isinstance(arr, list), "input should be a list of strings" + + # Helper function to perform backtracking + def backtrack(index, current_string): + # If the current string has duplicate characters, return 0 + if len(current_string) != len(set(current_string)): + return 0 + + # Calculate the maximum length by trying to add each subsequent string + max_length = len(current_string) + for i in range(index, len(arr)): + max_length = max(max_length, backtrack(i + 1, current_string + arr[i])) + return max_length + + # Start the backtracking from index 0 and an empty string + return backtrack(0, "") From b7266a4f64125a2c8c5ceacb50669b6a760aeb85 Mon Sep 17 00:00:00 2001 From: kefahalshaer Date: Sun, 12 Jan 2025 23:12:04 +0200 Subject: [PATCH 48/48] upload test_maximum_length.py file --- solutions/tests/test_maximum_length.py | 70 ++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 solutions/tests/test_maximum_length.py diff --git a/solutions/tests/test_maximum_length.py b/solutions/tests/test_maximum_length.py new file mode 100644 index 000000000..e4b7b1d94 --- /dev/null +++ b/solutions/tests/test_maximum_length.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Test module for maximum_length function. + +Test categories: + - Standard cases: list of strings that may have unique or overlapping characters + - Edge cases: empty lists, strings with identical bounds or duplicate characters, substrings with repetitive letters + - Defensive tests: invalid inputs, assertions, or `TypeError` exceptions + +Created on 2024-01-12 +Author: Kefah Albashityalshaer +""" + +import unittest + +from ..maximum_length import max_length + + +class TestMaxLengthFunction(unittest.TestCase): + # Standard test cases + def test_basic_cases(self): + self.assertEqual( + max_length(["un", "iq", "ue"]), 4 + ) # "uniq" forms a concatenated string of length 4 + self.assertEqual( + max_length(["cha", "r", "act", "ers"]), 6 + ) # The longest concatenated string is "acters" (length 6) + self.assertEqual( + max_length(["abcdefghijklmnopqrstuvwxyz"]), 26 + ) # The string contains all unique lowercase letters (length 26) + + # Edge Cases + def test_empty_list(self): + self.assertEqual( + max_length([]), 0 + ) # No strings to concatenate, so the result is 0 + + def test_single_element(self): + self.assertEqual(max_length(["a"]), 1) + self.assertEqual(max_length(["abcdef"]), 6) + + def test_no_unique_concatenation(self): + self.assertEqual(max_length(["a", "bb", "ccc"]), 1) + + def test_repeated_characters(self): + self.assertEqual(max_length(["abc", "def", "abc"]), 6) + + def test_large_input(self): + arr = ["ab", "cd", "ef", "gh", "ij", "kl", "mnop"] + self.assertEqual(max_length(arr), 16) # Longest possible combination + + # Defensive tests + def test_invalid_input(self): + with self.assertRaises( + AssertionError, + msg="Input should raise an AssertionError for non-list input.", + ): + max_length("not a list") + + def test_non_string_input(self): + with self.assertRaises(TypeError): + max_length(["abc", 123, "def"]) + + def test_empty_strings(self): + self.assertEqual(max_length(["", "abc", "de"]), 5) + + +if __name__ == "__main__": + unittest.main()