Practical numbers: Difference between revisions
Content added Content deleted
m (J implementation) |
|||
Line 236: | Line 236: | ||
STRETCH GOAL: 666 is Practical.</pre> |
STRETCH GOAL: 666 is Practical.</pre> |
||
====Python: |
====Python: Faster version==== |
||
This version has an optimisation that |
This version has an optimisation that proves ''much'' faster when testing a range of numbers for Practicality. |
||
A number with a large number of factors, f has <code>2**len(f)</code> sets in its powerset. 672 for example has 23 factors and so 8_388_608 sets in its powerset.<br> |
A number with a large number of factors, f has <code>2**len(f)</code> sets in its powerset. 672 for example has 23 factors and so 8_388_608 sets in its powerset.<br> |
||
Line 243: | Line 243: | ||
the sets. 720, another Practical number needs just 0.01% of its half a billion sets to prove it is Practical. |
the sets. 720, another Practical number needs just 0.01% of its half a billion sets to prove it is Practical. |
||
The inner loop is sensitive to the order of factors passed to the powerset generator and [XXX experimentation shows] that reverse sorting the factors saves the most computation. |
|||
Note however that if the number is '''not''' ultimately Practical, with a large number of factors, then the loop to find this is slightly ''slower''. |
|||
⚫ | |||
""" |
|||
Is x a practical number. |
|||
⚫ | |||
I.e. Can some selection of the proper divisors of x, (other than x), sum |
|||
"""Practical number test with factor reverse sort and short-circuiting.""" |
|||
to i for all i in the range 1..x-1 inclusive. |
|||
Can short-circuit summations for x with large number of factors >= __switch |
|||
""" |
|||
if x == 1: |
if x == 1: |
||
return True |
return True |
||
Line 261: | Line 256: | ||
if x > 2 and not mult_4_or_6: |
if x > 2 and not mult_4_or_6: |
||
return False # If > 2 then must be a divisor of 4 or 6 |
return False # If > 2 then must be a divisor of 4 or 6 |
||
⚫ | |||
⚫ | |||
⚫ | |||
if len(f) < __switch: |
|||
⚫ | |||
found = {y for y in {sum(i) for i in ps} |
|||
if 1 <= y < x} |
|||
found = set() |
|||
for nps in ps: |
|||
if len(found) < x - 1: |
|||
y = sum( |
y = sum(nps) |
||
if 1 <= y < x: |
if 1 <= y < x: |
||
found.add(y) |
found.add(y) |
||
else: |
|||
break # Short-circuiting the loop. |
|||
return len(found) == x - 1 |
return len(found) == x - 1 |
||
if __name__ == '__main__': |
|||
n = 333 |
|||
print("\n" + is_practical5.__doc__) |
|||
p = [x for x in range(1, n + 1) if is_practical5(x)] |
|||
print(f"There are {len(p)} Practical numbers from 1 to {n}:") |
|||
print(' ', str(p[:10])[1:-1], '...', str(p[-10:])[1:-1]) |
|||
x = 666 |
|||
print(f"\nSTRETCH GOAL: {x} is {'not ' if not is_practical(x) else ''}Practical.") |
|||
x = 5184 |
|||
print(f"\nEXTRA GOAL: {x} is {'not ' if not is_practical(x) else ''}Practical.")</lang> |
|||
{{out}} |
{{out}} |
||
Using the definition of factors5 from the simple case above then the following results are obtained. |
|||
<pre>Practical number test with factor reverse sort and short-circuiting. |
|||
⚫ | |||
There are 77 Practical numbers from 1 to 333: |
|||
1, 2, 4, 6, 8, 12, 16, 18, 20, 24 ... 288, 294, 300, 304, 306, 308, 312, 320, 324, 330 |
|||
STRETCH GOAL: 666 is Practical. |
|||
EXTRA GOAL: 5184 is Practical.</pre> |
|||
⚫ | |||
A little further investigation shows that you need to get to 3850, for the first example of a number with 23 or more factors that is not Practical.<br> |
A little further investigation shows that you need to get to 3850, for the first example of a number with 23 or more factors that is not Practical.<br> |
||
Around 1/8'th of the integers up to the 10_000'th Practical number have more than 22 factors but are '''not''' practical numbers themselves. (Some of these have 31 factors whilst being divisible by four or six so need the long loop)! |
Around 1/8'th of the integers up to the 10_000'th Practical number have more than 22 factors but are '''not''' practical numbers themselves. (Some of these have 31 factors whilst being divisible by four or six so would need the long loop to complete)! |
||
===Composition of pure functions=== |
===Composition of pure functions=== |