From 4c0b2b3b449d7666f9025ea57ed3d75296616dda Mon Sep 17 00:00:00 2001 From: amandapanda00 Date: Tue, 2 Dec 2025 01:40:49 -0500 Subject: [PATCH 1/2] Add armstrong number checker by amandapanda00. main.py, test_main.py, numbers.txt, readme.md --- .../armstrong_number_checker/README.md | 84 +++++++++++++++ .../armstrong_number_checker/main.py | 100 ++++++++++++++++++ .../armstrong_number_checker/numbers.txt | 7 ++ .../armstrong_number_checker/test_main.py | 15 +++ 4 files changed, 206 insertions(+) create mode 100644 week1_projects/amandapanda00/armstrong_number_checker/README.md create mode 100644 week1_projects/amandapanda00/armstrong_number_checker/main.py create mode 100644 week1_projects/amandapanda00/armstrong_number_checker/numbers.txt create mode 100644 week1_projects/amandapanda00/armstrong_number_checker/test_main.py diff --git a/week1_projects/amandapanda00/armstrong_number_checker/README.md b/week1_projects/amandapanda00/armstrong_number_checker/README.md new file mode 100644 index 0000000..895f722 --- /dev/null +++ b/week1_projects/amandapanda00/armstrong_number_checker/README.md @@ -0,0 +1,84 @@ +Amandapanda00 – Armstrong Number Checker +What the project does: +This project determines whether a given integer is an Armstrong number—a number equal to the sum of the cubes of its digits equals the number itself (153 = 1³ + 5³ + 3³ = 153). + +How to run it: +1. Make sure Python is installed on your computer. +2. Clone or download this repository. +3. Open the project in an environment that supports Python such as VS code or PyCharm. +4. Run the `main.py` file. +5. When prompted, choose an input method: + +* Keyboard input: Enter a number directly. + +* File input: Enter a filename to check numbers from a file (e.g., numbers.txt). + The program will read each line and check if it is an Armstrong number. + Invalid lines are skipped with a message for the user. + +Example input/output + +Example Input: + +153 + +Expected Output: + +153 is an Armstrong number + +Another Example: + +numbers.txt file + +Line 1: abc: Raises a ValueError when converting to int. The program prints: +Invalid entry on line 1: 'abc' + +Line 2: 123 = Successfully converted to an integer. Checked by is_armstrong(). Output: +123 is not an Armstrong number. + +Line 3: 153 = Successfully converted to an integer. Checked by is_armstrong(). Output: +153 is an Armstrong number. + +Line 4: 370 = Successfully converted to an integer. Checked by is_armstrong(). Output: +370 is an Armstrong number. + +Line 5: 456 = Successfully converted to an integer. Checked by is_armstrong(). Output: +456 is not an Armstrong number. + +Line 6: xyz Raises a ValueError. Output: +Invalid entry on line 6: 'xyz' + +Line 7: 9474 = Successfully converted to an integer. Checked by is_armstrong(). Output: +9474 is an Armstrong number. + +This file demonstrates: + +* Try/except blocks catching invalid data (abc and xyz). + +* Data integrity: only valid numbers are processed. File "r" read only. + +* File handling: reads multiple lines from a file. + + +Error Handling + +try/except blocks are used to handle invalid input/value errors. + +* This ensures the program is not going to crash if a user enters a non-integer value. + +* When reading a file, invalid entries are skipped, and the line number is reported to help track and identify errors. + +* File handling is done with "r" mode (read-only) to protect the file and prevent accidental changes. + + +Testing + +* PyCharm Debugger: Used to step through code and verify logic. + +* Pytest: Automatically tests the functionality of the Armstrong Number Checker, including both keyboard input and file input. Ensures that the program behaves correctly for a variety of cases. + +* Flake8: Checks code against Python style guidelines (PEP 8). + +* Pydocstyle: Checks that documentation is complete and clear, ensuring maintainability. + + + diff --git a/week1_projects/amandapanda00/armstrong_number_checker/main.py b/week1_projects/amandapanda00/armstrong_number_checker/main.py new file mode 100644 index 0000000..e65bbf4 --- /dev/null +++ b/week1_projects/amandapanda00/armstrong_number_checker/main.py @@ -0,0 +1,100 @@ +# Armstrong Number Checker +# Author: amandapanda00 +# Date: 11/04/2025 + +""" +This program checks whether a given integer is an Armstrong number. + +An Armstrong number is equal to the sum of the cubes of its digits. +""" + + +def is_armstrong(number): + """ + Determine whether a given integer is an Armstrong number. + + Parameter: + number (int): The integer to be tested. + + Returns: + bool: True if the number is an Armstrong number, False otherwise. + """ + digits = [int(d) for d in str(number)] + n = len(digits) # number of digits + # og had ** 3 + # change to n to accommodate armstrong numbers more than 3 digits + total = sum(d ** n for d in digits) + return total == number + + +def process_result(number): + """Print the result.""" + if is_armstrong(number): + print(f"{number} is an Armstrong number.") + else: + print(f"{number} is not an Armstrong number.") + + +def process_file(filename="numbers.txt"): + """ + Read multiple lines from a file and check each one. + + See if it is an Armstrong number. + """ + try: + with open(filename, "r") as file: + # read only to keep integrity of data + for line_num, line in enumerate(file, start=1): + # loop through data in file + # number each line in file starting with 1 + # keep track of bad data + line = line.strip() + # removes newline ect. cleans line + + # Only process the line if it is not empty + if line: + try: + number = int(line) + process_result(number) + except ValueError: + print(f"Invalid entry on line {line_num}: '{line}'") + # If the line is empty do nothing + # print error for user clarity + + except FileNotFoundError: + print(f"Error: File '{filename}' not found.") + except PermissionError: + print(f"Error: Not allowed to read '{filename}'.") + + +def main(): + """Run main.""" + print("Choose input method:") + print("1. Enter a number using the keyboard") + print("2. Read a number from a file") + # print user menu + + choice = input("Enter choice (1 or 2): ").strip() + # get user choice + # strip cleans input-user errors, extra spaces + + if choice == "1": + try: + num = int(input("Enter a number: ")) + # string to int + process_result(num) + # call function + except ValueError: + print("Invalid input. Please enter a valid integer.") + # value error to fail gracefully. abc != 123 + + elif choice == "2": + filename = input("Enter filename: ").strip() + process_file(filename) + + else: + print("Invalid choice.") + + +if __name__ == "__main__": + main() diff --git a/week1_projects/amandapanda00/armstrong_number_checker/numbers.txt b/week1_projects/amandapanda00/armstrong_number_checker/numbers.txt new file mode 100644 index 0000000..cbfc1a7 --- /dev/null +++ b/week1_projects/amandapanda00/armstrong_number_checker/numbers.txt @@ -0,0 +1,7 @@ +abc +123 +153 +370 +456 +xyz +9474 \ No newline at end of file diff --git a/week1_projects/amandapanda00/armstrong_number_checker/test_main.py b/week1_projects/amandapanda00/armstrong_number_checker/test_main.py new file mode 100644 index 0000000..b53c549 --- /dev/null +++ b/week1_projects/amandapanda00/armstrong_number_checker/test_main.py @@ -0,0 +1,15 @@ +from main import is_armstrong + + +def test_3_digit_armstrong(): + assert is_armstrong(153) + assert not is_armstrong(123) + + +def test_4_digit_armstrong(): + assert is_armstrong(9474) + assert not is_armstrong(9475) + + +def test_1_digit_armstrong(): + assert is_armstrong(5) From 5ad71bc9609a809c6e1c8cfc2a234027b603afa3 Mon Sep 17 00:00:00 2001 From: amandapanda00 Date: Wed, 3 Dec 2025 01:02:56 -0500 Subject: [PATCH 2/2] imporvments after PR feedback updated main, testing, and read me --- .../armstrong_number_checker/README.md | 43 +++++++++++++++- .../armstrong_number_checker/main.py | 49 ++++++++----------- .../armstrong_number_checker/numbers.txt | 4 +- .../armstrong_number_checker/test_main.py | 4 ++ 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/week1_projects/amandapanda00/armstrong_number_checker/README.md b/week1_projects/amandapanda00/armstrong_number_checker/README.md index 895f722..6a46162 100644 --- a/week1_projects/amandapanda00/armstrong_number_checker/README.md +++ b/week1_projects/amandapanda00/armstrong_number_checker/README.md @@ -1,6 +1,14 @@ Amandapanda00 – Armstrong Number Checker What the project does: -This project determines whether a given integer is an Armstrong number—a number equal to the sum of the cubes of its digits equals the number itself (153 = 1³ + 5³ + 3³ = 153). +This project determines whether a given integer is an Armstrong number. An Armstrong number is a number that is equal to the sum of its digits, each raised to the power of the number of digits. (153 = 1³ + 5³ + 3³ = 153). + +The program allows you to: + +* Enter numbers directly from the keyboard, or + +* Read and process multiple numbers from a file. + +It includes proper error handling, file-processing safety, and clear output formatting. How to run it: 1. Make sure Python is installed on your computer. @@ -50,6 +58,12 @@ Invalid entry on line 6: 'xyz' Line 7: 9474 = Successfully converted to an integer. Checked by is_armstrong(). Output: 9474 is an Armstrong number. +Line 8: -45 = Successfully converted to an integer. Checked by is_armstrong(). Output: +-45 is not an Armstrong number. + +Line 9: -153 = Successfully converted to an integer. Checked by is_armstrong(). Output: +-153 is not an Armstrong number. + This file demonstrates: * Try/except blocks catching invalid data (abc and xyz). @@ -80,5 +94,32 @@ Testing * Pydocstyle: Checks that documentation is complete and clear, ensuring maintainability. +Updates Included in This Version + +1. process_result() now returns a string instead of printing directly. This improves testability and separation of concerns. + +2. main() is updated so all printing happens in one place, following recommended best practices. + +3. Improved documentation for clarity. + +4. Updated file-processing function to include: +* Files are opened using encoding="utf-8" to ensure proper handling of characters in different environments and locales. + +* This prevents issues with non-ASCII characters and ensures consistent behavior across operating systems. + + +Future Improvements / Suggestions + +Here are recommended enhancements that could be added: + + +* Add GUI version + +* Limit maximum allowed digits/value to avoid CPU/memory DoS from huge inputs and report if input is too large. + +* Expand pytest coverage to include file-processing tests + +* Add a GitHub Actions workflow + diff --git a/week1_projects/amandapanda00/armstrong_number_checker/main.py b/week1_projects/amandapanda00/armstrong_number_checker/main.py index e65bbf4..0b7d5d9 100644 --- a/week1_projects/amandapanda00/armstrong_number_checker/main.py +++ b/week1_projects/amandapanda00/armstrong_number_checker/main.py @@ -1,11 +1,11 @@ # Armstrong Number Checker # Author: amandapanda00 # Date: 11/04/2025 - """ This program checks whether a given integer is an Armstrong number. -An Armstrong number is equal to the sum of the cubes of its digits. +An Armstrong number is equal to the sum of its digits each raised +to the power of the number of digits. """ @@ -13,53 +13,51 @@ def is_armstrong(number): """ Determine whether a given integer is an Armstrong number. + An Armstrong number equals the sum of its digits raised to the power + of the number of digits. Negative numbers automatically return False. + Parameter: number (int): The integer to be tested. Returns: bool: True if the number is an Armstrong number, False otherwise. """ + if number < 0: + return False # negative numbers are not Armstrong numbers + digits = [int(d) for d in str(number)] - n = len(digits) # number of digits - # og had ** 3 - # change to n to accommodate armstrong numbers more than 3 digits + n = len(digits) total = sum(d ** n for d in digits) return total == number def process_result(number): - """Print the result.""" + """Return the formatted Armstrong result string.""" if is_armstrong(number): - print(f"{number} is an Armstrong number.") + return f"{number} is an Armstrong number." else: - print(f"{number} is not an Armstrong number.") + return f"{number} is not an Armstrong number." def process_file(filename="numbers.txt"): """ - Read multiple lines from a file and check each one. + Read lines from a file and test each entry to determine whether it + is an Armstrong number. - See if it is an Armstrong number. + Invalid lines and empty lines are skipped with an explanation. """ try: - with open(filename, "r") as file: - # read only to keep integrity of data + with open(filename, "r", encoding="utf-8") as file: for line_num, line in enumerate(file, start=1): - # loop through data in file - # number each line in file starting with 1 - # keep track of bad data line = line.strip() - # removes newline ect. cleans line - # Only process the line if it is not empty if line: try: number = int(line) - process_result(number) + result = process_result(number) + print(result) except ValueError: print(f"Invalid entry on line {line_num}: '{line}'") - # If the line is empty do nothing - # print error for user clarity except FileNotFoundError: print(f"Error: File '{filename}' not found.") @@ -68,25 +66,20 @@ def process_file(filename="numbers.txt"): def main(): - """Run main.""" + """Run the main program menu and input handling.""" print("Choose input method:") print("1. Enter a number using the keyboard") print("2. Read a number from a file") - # print user menu choice = input("Enter choice (1 or 2): ").strip() - # get user choice - # strip cleans input-user errors, extra spaces if choice == "1": try: num = int(input("Enter a number: ")) - # string to int - process_result(num) - # call function + result = process_result(num) + print(result) except ValueError: print("Invalid input. Please enter a valid integer.") - # value error to fail gracefully. abc != 123 elif choice == "2": filename = input("Enter filename: ").strip() diff --git a/week1_projects/amandapanda00/armstrong_number_checker/numbers.txt b/week1_projects/amandapanda00/armstrong_number_checker/numbers.txt index cbfc1a7..6a0fd9f 100644 --- a/week1_projects/amandapanda00/armstrong_number_checker/numbers.txt +++ b/week1_projects/amandapanda00/armstrong_number_checker/numbers.txt @@ -4,4 +4,6 @@ abc 370 456 xyz -9474 \ No newline at end of file +9474 +-45 +-153 \ No newline at end of file diff --git a/week1_projects/amandapanda00/armstrong_number_checker/test_main.py b/week1_projects/amandapanda00/armstrong_number_checker/test_main.py index b53c549..9507543 100644 --- a/week1_projects/amandapanda00/armstrong_number_checker/test_main.py +++ b/week1_projects/amandapanda00/armstrong_number_checker/test_main.py @@ -13,3 +13,7 @@ def test_4_digit_armstrong(): def test_1_digit_armstrong(): assert is_armstrong(5) + + +def test_negative_number(): + assert not is_armstrong(-153)