Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add algorithm 95 to find the longest amicable chain #12113

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
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
Empty file.
65 changes: 65 additions & 0 deletions project_euler/problem_095/sol1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
Project Euler Problem: https://projecteuler.net/problem=95

An amicable chain is a sequence of numbers where each number is the sum of the proper divisors of the previous one, and the chain eventually returns to the starting number.

Check failure on line 4 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

project_euler/problem_095/sol1.py:4:89: E501 Line too long (172 > 88)

The problem is to find the smallest member of the longest amicable chain under a given limit.

Check failure on line 6 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

project_euler/problem_095/sol1.py:6:89: E501 Line too long (93 > 88)

In this implementation, we aim to identify all amicable chains and find the one with the maximum length, while also returning the smallest member of that chain.

Check failure on line 8 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

project_euler/problem_095/sol1.py:8:89: E501 Line too long (160 > 88)
"""

def sum_of_proper_divisors(n):
abda-gaye marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

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

Please provide return type hint for the function: sum_of_proper_divisors. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function sum_of_proper_divisors

Please provide type hint for the parameter: n

Please provide descriptive name for the parameter: n

Choose a reason for hiding this comment

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

Please provide return type hint for the function: sum_of_proper_divisors. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function sum_of_proper_divisors

Please provide type hint for the parameter: n

Please provide descriptive name for the parameter: n

"""Calculate the sum of proper divisors of n."""
if n < 2:
return 0 # Proper divisors of 0 and 1 are none.
total = 1 # Start with 1, since it is a proper divisor of any n > 1
sqrt_n = int(n**0.5) # Calculate the integer square root of n.

Check failure on line 17 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

project_euler/problem_095/sol1.py:17:1: W293 Blank line contains whitespace
# Loop through possible divisors from 2 to the square root of n
for i in range(2, sqrt_n + 1):
if n % i == 0: # Check if i is a divisor of n
total += i # Add the divisor
if i != n // i: # Avoid adding the square root twice
total += n // i # Add the corresponding divisor (n/i)

Check failure on line 24 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

project_euler/problem_095/sol1.py:24:1: W293 Blank line contains whitespace
return total

def find_longest_amicable_chain(limit):

Choose a reason for hiding this comment

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

Please provide return type hint for the function: find_longest_amicable_chain. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function find_longest_amicable_chain

Please provide type hint for the parameter: limit

Copy link
Author

Choose a reason for hiding this comment

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

it's okay

Choose a reason for hiding this comment

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

Please provide return type hint for the function: find_longest_amicable_chain. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function find_longest_amicable_chain

Please provide type hint for the parameter: limit

Choose a reason for hiding this comment

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

Please provide return type hint for the function: find_longest_amicable_chain. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function find_longest_amicable_chain

Please provide type hint for the parameter: limit

"""Find the smallest member of the longest amicable chain under a given limit."""
sum_divisors = {} # Dictionary to store the sum of proper divisors for each number
for i in range(1, limit + 1):
sum_divisors[i] = sum_of_proper_divisors(i) # Calculate and store sum of proper divisors

Check failure on line 31 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

project_euler/problem_095/sol1.py:31:89: E501 Line too long (97 > 88)

longest_chain = [] # To store the longest amicable chain found
seen = {} # Dictionary to track numbers already processed

# Iterate through each number to find amicable chains
for start in range(1, limit + 1):
if start in seen: # Skip if this number is already processed
continue

chain = [] # Initialize the current chain
current = start # Start with the current number
while current <= limit and current not in chain:
chain.append(current) # Add the current number to the chain
seen[current] = True # Mark this number as seen
current = sum_divisors.get(current, 0) # Move to the next number in the chain

Check failure on line 46 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

project_euler/problem_095/sol1.py:46:89: E501 Line too long (90 > 88)

# Check if we form a cycle and validate the chain
if current in chain and current != start:
cycle_start_index = chain.index(current) # Find where the cycle starts
if current in sum_divisors and sum_divisors[current] in chain:
# This means we have a valid amicable chain
chain = chain[cycle_start_index:] # Take only the cycle part
if len(chain) > len(longest_chain):
longest_chain = chain # Update longest chain if this one is longer

return min(longest_chain) if longest_chain else None # Return the smallest member of the longest chain

Check failure on line 57 in project_euler/problem_095/sol1.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

project_euler/problem_095/sol1.py:57:89: E501 Line too long (107 > 88)

def solution():

Choose a reason for hiding this comment

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

Please provide return type hint for the function: solution. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function solution

Copy link
Author

Choose a reason for hiding this comment

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

it's okay

Choose a reason for hiding this comment

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

Please provide return type hint for the function: solution. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function solution

Choose a reason for hiding this comment

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

Please provide return type hint for the function: solution. If the function does not return a value, please provide the type hint as: def function() -> None:

As there is no test file in this pull request nor any test function or class in the file project_euler/problem_095/sol1.py, please provide doctest for the function solution

"""Return the smallest member of the longest amicable chain under one million."""
return find_longest_amicable_chain(10**6)

if __name__ == "__main__":
smallest_member = solution() # Call the solution function
print(smallest_member) # Output the smallest member of the longest amicable chain
Loading