1
Incremental Development: Hypotenuse and Factorial
CS 1101-01 Programming Fundamentals - AY2025-T4
Programming Assignment Unit 4
Instructor: Jose Alvarado
May 8, 2025
2
Part 1: Incremental Development of Hypotenuse Function
Stage 1: Function Definition:
At the first stage, we define the hypotenuse function that takes two arguments, representing the
lengths of the two legs of a right triangle. We will then import the math module to utilize the
square root function for calculating the hypotenuse.
import math
def hypotenuse(a, b):
# Calculate the hypotenuse based on the Pythagorean theorem: c^2 = a^2 + b^2
return math.sqrt(a**2 + b**2)
# Testing the function with the initial inputs
print(hypotenuse(3, 4)) # Expected output: 5.0
Output: 5.0
Stage 2: Adding Type Annotations:
In this stage, we will add type annotations to the function parameters to indicate that they should
be numbers (either integers or floats). This helps code readability and future developers
understand the expected input types.
import math
def hypotenuse(a: float, b: float) -> float:
return math.sqrt(a**2 + b**2)
# Testing the function with known inputs
3
print(hypotenuse(3, 4)) # Output: 5.0
# Additional tests
print(hypotenuse(5, 12)) # Expected output: 13.0
print(hypotenuse(8, 15)) # Expected output: 17.0
Output:
5.0
13.0
17.0
Stage 3 Adding Input Validation:
The final stage involves implementing input validation to ensure that the arguments are
nonnegative. This helps prevent errors when invalid input is provided.
import math
def hypotenuse(a: float, b: float) -> float:
if a < 0 or b < 0:
raise ValueError("Lengths of the legs must be non-negative.")
return math.sqrt(a**2 + b**2)
# Testing our function with valid inputs
print(hypotenuse(3, 4)) # Output: 5.0
print(hypotenuse(5, 12)) # Output: 13.0
print(hypotenuse(8, 15)) # Output: 17.0
4
Output:
5.0
13.0
17.0
We can also test the input validation:
try:
print(hypotenuse(-3, 4)) # Should raise a ValueError
except ValueError as e:
print(f"Error: {e}")
Output:
Error: Lengths of the legs must be non-negative.
In summary, the incremental development approach allowed us to build a robust and efficient
hypotenuse function by gradually adding features and addressing potential issues at each stage.
5
Part 2: Incremental Development of a Factorial Function
For the second part of this assignment, I will create a function to compute the factorial of a
nonnegative integer using an incremental development approach
Stage 1 Basic Function Definition:
The initial stage involves defining the factorial function. In this stage, I will create a simple
recursive implementation.
def factorial(n: int) -> int:
# Base case: factorial of 0 is 1
if n == 0:
return 1
# Recursive case
return n * factorial(n - 1)
# Testing with initial input
print(factorial(5)) # Expected output: 120
Output: 120
Stage 2 Adding Input Validation:
Next, I will implement input validation to ensure that the input is a non-negative integer
6
def factorial(n: int) -> int:
if n < 0:
raise ValueError("Factorial is not defined for negative numbers.")
if n == 0:
return 1
return n * factorial(n - 1)
# Testing valid input
print(factorial(5)) # Output: 120
print(factorial(0)) # Output: 1
# Testing invalid input
try:
print(factorial(-1)) # Should raise a ValueError
except ValueError as e:
print(f"Error: {e}")
Output:
120
1
Error: Factorial is not defined for negative numbers.
7
Stage 3 Optimizing with Iterative Approach:
In the final stage, I will replace the recursive approach with an iterative one for efficiency and to
support larger values of n without the risk of exceeding the maximum recursion depth.
def factorial(n: int) -> int:
if n < 0:
raise ValueError("Factorial is not defined for negative numbers.")
result = 1
for i in range(1, n + 1):
result *= i
return result
# Testing with various inputs
print(factorial(5)) # Output: 120
print(factorial(6)) # Output: 720
print(factorial(10)) # Output: 3628800
print(factorial(12)) # Output: 479001600
Output:
120
720
3628800
479001600
8
In conclusion, the iterative approach to calculating the factorial not only avoids recursion depth
issues but also demonstrates a more efficient solution for larger input values. The incremental
development process ensured that each stage built upon the previous one, resulting in a reliable
and well-tested function.
9
Reference
Downey, A. (2015). Think Python: How to think like a computer scientist. Green Tree Press.
https://greenteapress.com/thinkpython2/thinkpython2.pdf
Python Official Documentation. (n.d.). Retrieved from https://docs.python.org/3/