Skip to content

Commit 165f8e4

Browse files
committed
Adding alternative (MUCH faster) algorithm for Achilles Numbers in Python. Not replacing existing as logic is drastically different.
1 parent b705988 commit 165f8e4

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Script to find the n-th Achilles Number in sequence
2+
# Achilles Numbers are defined as a Powerful number, but not a Perfect Power
3+
# Powerful numbers can be defined as all prime factors of the number (p) also have p^2 as a factor.
4+
# As prime factors will already be found, determining a Perfect Power is as simple
5+
# as determining if the GCD of all powers = 1.
6+
7+
# math is used to calculate GCD of the list of prime factors
8+
import math
9+
# functools is used to apply the math.gcd function to a list of factors (as opposed to just two factors)
10+
# As of Python 3.9, could just use the math.gcd() function as it allows a list input now.
11+
import functools
12+
13+
14+
# Function to return a list of prime factors
15+
def get_prime_factors(n):
16+
i = 2
17+
factors = []
18+
while i * i <= n:
19+
# loop through each integer up to the square root of n
20+
if n % i == 0:
21+
# if it is a factor, add it to the list for returning later
22+
factors.append(i)
23+
# reduce the remaining number by the factor appended
24+
n //= i
25+
else:
26+
# otherwise, try the next integer
27+
i += 1
28+
29+
if n > 1:
30+
# then there is a remaining factor
31+
factors.append(n)
32+
33+
return factors
34+
35+
36+
# Function to return a list of the factor powers based on a list of prime factors passed
37+
def factor_powers(factors):
38+
powers = []
39+
# Use prior_factor to compare if it's the same as the previous factor
40+
prior_factor = factors[0]
41+
i = 0
42+
for a in factors:
43+
# If the next item in the list is the same factor, increase the count
44+
if a == prior_factor:
45+
i += 1
46+
# Otherwise, append the count that's there, reset the count to 1 and start matching to the new factor
47+
else:
48+
powers.append(i)
49+
i = 1
50+
prior_factor = a
51+
# Have to append a count of the last factor
52+
powers.append(i)
53+
return powers
54+
55+
56+
def is_powerful(powers):
57+
if min(powers) >= 2:
58+
return True
59+
else:
60+
return False
61+
62+
63+
def is_perfect_power(powers):
64+
if len(powers) <= 1:
65+
return True
66+
elif len(powers) == 2:
67+
return math.gcd(powers[0], powers[1]) != 1
68+
elif len(powers) >= 3:
69+
return functools.reduce(math.gcd, powers) != 1
70+
else:
71+
return False
72+
73+
74+
def is_achilles(n):
75+
# First retrieve the powers of all prime factors
76+
powers = factor_powers(get_prime_factors(n))
77+
# Then return if it is powerful, but no a perfect power
78+
return is_powerful(powers) and not is_perfect_power(powers)
79+
80+
81+
# Main program to prompt for the sequence number and loop to find that n in the sequence
82+
83+
num = int(input('Enter n: '))
84+
count = 0
85+
current = 2
86+
while count < num:
87+
current += 1
88+
if is_achilles(current):
89+
count += 1
90+
print(current)

0 commit comments

Comments
 (0)