2929"""
3030from __future__ import annotations
3131
32- import math
33-
3432
3533def get_pascal_triangle_unique_coefficients (depth : int ) -> set [int ]:
3634 """
@@ -61,76 +59,9 @@ def get_pascal_triangle_unique_coefficients(depth: int) -> set[int]:
6159 return coefficients
6260
6361
64- def get_primes_squared (max_number : int ) -> list [int ]:
65- """
66- Calculates all primes between 2 and round(sqrt(max_number)) and returns
67- them squared up.
68-
69- >>> get_primes_squared(2)
70- []
71- >>> get_primes_squared(4)
72- [4]
73- >>> get_primes_squared(10)
74- [4, 9]
75- >>> get_primes_squared(100)
76- [4, 9, 25, 49]
77- """
78- max_prime = math .isqrt (max_number )
79- non_primes = [False ] * (max_prime + 1 )
80- primes = []
81- for num in range (2 , max_prime + 1 ):
82- if non_primes [num ]:
83- continue
84-
85- for num_counter in range (num ** 2 , max_prime + 1 , num ):
86- non_primes [num_counter ] = True
87-
88- primes .append (num ** 2 )
89- return primes
90-
91-
92- def get_squared_primes_to_use (
93- num_to_look : int , squared_primes : list [int ], previous_index : int
94- ) -> int :
95- """
96- Returns an int indicating the last index on which squares of primes
97- in primes are lower than num_to_look.
98-
99- This method supposes that squared_primes is sorted in ascending order and that
100- each num_to_look is provided in ascending order as well. Under these
101- assumptions, it needs a previous_index parameter that tells what was
102- the index returned by the method for the previous num_to_look.
103-
104- If all the elements in squared_primes are greater than num_to_look, then the
105- method returns -1.
106-
107- >>> get_squared_primes_to_use(1, [4, 9, 16, 25], 0)
108- -1
109- >>> get_squared_primes_to_use(4, [4, 9, 16, 25], 0)
110- 1
111- >>> get_squared_primes_to_use(16, [4, 9, 16, 25], 1)
112- 3
62+ def get_squarefrees (unique_coefficients : set [int ]) -> set [int ]:
11363 """
114- idx = max (previous_index , 0 )
115-
116- while idx < len (squared_primes ) and squared_primes [idx ] <= num_to_look :
117- idx += 1
118-
119- if idx == 0 and squared_primes [idx ] > num_to_look :
120- return - 1
121-
122- if idx == len (squared_primes ) and squared_primes [- 1 ] > num_to_look :
123- return - 1
124-
125- return idx
126-
127-
128- def get_squarefree (
129- unique_coefficients : set [int ], squared_primes : list [int ]
130- ) -> set [int ]:
131- """
132- Calculates the squarefree numbers inside unique_coefficients given a
133- list of square of primes.
64+ Calculates the squarefree numbers inside unique_coefficients.
13465
13566 Based on the definition of a non-squarefree number, then any non-squarefree
13667 n can be decomposed as n = p*p*r, where p is positive prime number and r
@@ -140,27 +71,27 @@ def get_squarefree(
14071 squarefree as r cannot be negative. On the contrary, if any r exists such
14172 that n = p*p*r, then the number is non-squarefree.
14273
143- >>> get_squarefree ({1}, [] )
144- set()
145- >>> get_squarefree ({1, 2}, [] )
146- set()
147- >>> get_squarefree ({1, 2, 3, 4, 5, 6, 7, 35, 10, 15, 20, 21}, [4, 9, 25] )
74+ >>> get_squarefrees ({1})
75+ {1}
76+ >>> get_squarefrees ({1, 2})
77+ {1, 2}
78+ >>> get_squarefrees ({1, 2, 3, 4, 5, 6, 7, 35, 10, 15, 20, 21})
14879 {1, 2, 3, 5, 6, 7, 35, 10, 15, 21}
14980 """
15081
151- if len (squared_primes ) == 0 :
152- return set ()
153-
15482 non_squarefrees = set ()
155- prime_squared_idx = 0
156- for num in sorted (unique_coefficients ):
157- prime_squared_idx = get_squared_primes_to_use (
158- num , squared_primes , prime_squared_idx
159- )
160- if prime_squared_idx == - 1 :
161- continue
162- if any (num % prime == 0 for prime in squared_primes [:prime_squared_idx ]):
163- non_squarefrees .add (num )
83+ for number in unique_coefficients :
84+ divisor = 2
85+ copy_number = number
86+ while divisor ** 2 <= copy_number :
87+ multiplicity = 0
88+ while copy_number % divisor == 0 :
89+ copy_number //= divisor
90+ multiplicity += 1
91+ if multiplicity >= 2 :
92+ non_squarefrees .add (number )
93+ break
94+ divisor += 1
16495
16596 return unique_coefficients .difference (non_squarefrees )
16697
@@ -170,15 +101,14 @@ def solution(n: int = 51) -> int:
170101 Returns the sum of squarefrees for a given Pascal's Triangle of depth n.
171102
172103 >>> solution(1)
173- 0
104+ 1
174105 >>> solution(8)
175106 105
176107 >>> solution(9)
177108 175
178109 """
179110 unique_coefficients = get_pascal_triangle_unique_coefficients (n )
180- primes = get_primes_squared (max (unique_coefficients ))
181- squarefrees = get_squarefree (unique_coefficients , primes )
111+ squarefrees = get_squarefrees (unique_coefficients )
182112 return sum (squarefrees )
183113
184114
0 commit comments