Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions week1_projects/amandapanda00/armstrong_number_checker/README.md
Original file line number Diff line number Diff line change
@@ -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.



100 changes: 100 additions & 0 deletions week1_projects/amandapanda00/armstrong_number_checker/main.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @amandapanda00 — thanks for the contribution! I reviewed week1_projects/amandapanda00/armstrong_number_checker/main.py. Please make the following changes to improve correctness, robustness, and maintainability:

  1. Fix module docstring
  • Change "sum of the cubes of its digits" to the general definition: an Armstrong number equals the sum of each digit raised to the power of the number of digits.
  1. Handle negative input
  • Reject negative integers (return False) or explicitly document that only non-negative integers are supported. Current code will crash on negative input because of the '-' character in str(number).

Suggested change:
def is_armstrong(number: int) -> bool:
if number < 0:
return False
digits = [int(d) for d in str(number)]
n = len(digits)
return sum(d ** n for d in digits) == number

  1. Improve file handling
  • Open files with explicit encoding (encoding="utf-8").
  • Prefer pathlib.Path for clearer checks (exists/is_file).
  • Keep existing FileNotFoundError/PermissionError handling but check path first to provide clearer messages.
  1. Make functions more testable
  • Keep is_armstrong pure (it already is).
  • Have process_result return the formatted string instead of printing directly; main() can print it. This makes unit testing easier.
  1. Input robustness and UX
  • Catch KeyboardInterrupt and EOFError in main to exit gracefully.
  • Validate filename input (strip and ignore empty input).
  • Consider rejecting lines that contain non-digit characters (or handle leading '+') and report which lines are invalid.
  1. Clean up comments and add type hints
  • Remove noisy inline comments like "# og had ** 3".
  • Add type hints for public functions (e.g., process_file(filename: str) -> None).
  • Improve docstrings (PEP 257 style).
  1. Tests and CI
  • Add unit tests (pytest or unittest) covering:
    • Typical Armstrong numbers: 153, 370, 9474
    • Non-Armstrong numbers
    • 0
    • Negative values
    • File input with invalid lines
  • Consider adding a simple GitHub Actions workflow to run tests.
  1. Optional improvements (nice-to-have)
  • Use argparse for CLI options (single number vs filename).
  • Limit maximum allowed digits/value to avoid CPU/memory DoS from huge inputs and report if input is too large.

Original file line number Diff line number Diff line change
@@ -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()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
abc
123
153
370
456
xyz
9474
15 changes: 15 additions & 0 deletions week1_projects/amandapanda00/armstrong_number_checker/test_main.py
Original file line number Diff line number Diff line change
@@ -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)