Skip to content

Commit

Permalink
Merge pull request #39 from MIT-Emerging-Talent/largest-perfect-squar…
Browse files Browse the repository at this point in the history
…e-less-than-number

Largest perfect square less than number
  • Loading branch information
kimya-fayaz authored Jan 12, 2025
2 parents 8e53312 + 1e63f86 commit 938e9dc
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 1 deletion.
78 changes: 78 additions & 0 deletions solutions/largest_perfect_square_less_than_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
A module for finding the largest perfect square less than a given number.
Module contents:
- largest_perfect_square_less_than_number:
returns the largest perfect square that is less than the given number.
Created on 2025-01-06
@author: Huda Alamassi
"""

from typing import Union


def largest_perfect_square_less_than_number(number: Union[int, float]) -> int:
"""
The function takes in a number (either int or float) and returns the largest perfect square
that is less than the given number.
Arguments:
number (int, float): The input number to check for the largest perfect square less than it.
Assumptions:
- The input number must be a non-negative number (either integer or float).
Returns:
int:
- The largest perfect square that is less than the input number.
- If no perfect square exists (i.e., for inputs less than or equal to 1 or equal to 0),
the function will return 0.
Raises:
AssertionError: If the input is a negative number (integer or float).
AssertionError: If the input is not a number (neither integer nor float).
Examples:
>>> largest_perfect_square_less_than_number(50)
49
>>> largest_perfect_square_less_than_number(16.5)
9
>>> largest_perfect_square_less_than_number(1)
0
>>> largest_perfect_square_less_than_number(100.99)
81
"""
# Validate input type to avoid errors in mathematical operations
assert isinstance(number, (int, float)), (
"Input must be a number (either integer or float)."
)

# Negative numbers do not have valid perfect squares
assert number >= 0, "Input must be a non-negative number."

# Handle edge cases where no perfect square exists below 1
if number <= 1:
return 0

# Ensure we work with the integer part of the square root
square_root = int(number**0.5)

# Find the largest perfect square less than the number
perfect_square = square_root**2

# Adjust when the number is exactly or close to a perfect square
if perfect_square == int(number):
square_root -= 1
perfect_square = square_root**2

return perfect_square
1 change: 0 additions & 1 deletion solutions/tests/README.md
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
# Tests
92 changes: 92 additions & 0 deletions solutions/tests/test_largest_perfect_square_less_than_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Test module for largest_perfect_square_less_than function.
Contains tests for checking the functionality of finding
the largest perfect square less than a given number.
Test categories:
- Functionality tests: checking if the function correctly identifies
the largest perfect square less than a number.
- Edge tests:
- Small positive numbers (the input is less than or equal to 1)
- Perfect squares and slightly below or above it
- Very large numbers
- Zero
- Defensive tests: ensuring the function handles invalid inputs such as:
- Negative numbers
- Non-numeric inputs
Created on 2025-01-06
@author: Huda Alamassi
"""

import unittest

from solutions.largest_perfect_square_less_than_number import (
largest_perfect_square_less_than_number,
)


class TestLargestPerfectSquareLessThanNumber(unittest.TestCase):
"""Test the largest_perfect_square_less_than_number function."""

# Test functionality
def test_integer_input(self):
"""It should return the largest perfect square less than the given integer."""
actual = largest_perfect_square_less_than_number(50)
self.assertEqual(actual, 49)

def test_float_input(self):
"""It should return the largest perfect square less than the given float."""
actual = largest_perfect_square_less_than_number(2.6)
self.assertEqual(actual, 1)

# Test edge cases
def test_small_positive_number(self):
"""It should return 0 when the input is less than or equal to 1."""
actual = largest_perfect_square_less_than_number(0.5)
self.assertEqual(actual, 0)

def test_perfect_square(self):
"""It should return the largest perfect square less than the given perfect square."""
actual = largest_perfect_square_less_than_number(16)
self.assertEqual(actual, 9)

def test_slightly_above_perfect_square(self):
"""It should return the largest square less than input slightly above a perfect square."""
actual = largest_perfect_square_less_than_number(16.5)
self.assertEqual(actual, 9)

def test_slightly_below_perfect_square(self):
"""It should return the largest square less than input slightly below a perfect square."""
actual = largest_perfect_square_less_than_number(15.9)
self.assertEqual(actual, 9)

def test_very_large_number(self):
"""It should return the largest perfect square less than a very large input."""
actual = largest_perfect_square_less_than_number(10**6)
self.assertEqual(actual, 998001)

def test_zero(self):
"""It should return 0 when the input is 0."""
actual = largest_perfect_square_less_than_number(0)
self.assertEqual(actual, 0)

# Test defensive assertions
def test_defensive_assertion_for_negative_input(self):
"""It should raise an AssertionError when the input is negative."""
with self.assertRaises(AssertionError):
largest_perfect_square_less_than_number(-10)

def test_defensive_assertion_for_non_numeric_input(self):
"""It should raise an AssertionError when the input is not a number."""
with self.assertRaises(AssertionError):
largest_perfect_square_less_than_number("abc")

0 comments on commit 938e9dc

Please sign in to comment.