Skip to content

Commit 3768020

Browse files
Solve PE 800
1 parent 413ab9a commit 3768020

File tree

3 files changed

+120
-2
lines changed

3 files changed

+120
-2
lines changed

pdm.lock

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

project_euler/test_pe800.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# <https://projecteuler.net/problem=800>
2+
# <p>
3+
# An integer of the form $p^q q^p$ with prime numbers $p \neq q$ is called a <dfn>hybrid-integer</dfn>.<br>
4+
# For example, $800 = 2^5 5^2$ is a hybrid-integer.
5+
# </p>
6+
# <p>
7+
# We define $C(n)$ to be the number of hybrid-integers less than or equal to $n$.<br>
8+
# You are given $C(800) = 2$ and $C(800^{800}) = 10790$.
9+
# </p>
10+
# <p>
11+
# Find $C(800800^{800800})$.
12+
# </p>
13+
# Notes:
14+
# - sqrt(800800^800800) = HUGE
15+
# - log2(800800^800800) < 1.6 x 10^7
16+
# - Largest prime less than 1.6 x 10^7 is 1,599,9989
17+
# - Number of primes < 1.6 x 10^7 is 1,031,130
18+
# - log3(800800^800800) < 1.0 x 10^7
19+
# - Largest prime less than 1.0 x 10^7 is 9999_991
20+
# - Number of primes < 1.0 x 10^7 is 664579
21+
# - log5(800800^800800) < 6.8 x 10^6
22+
# - Largest prime less than is ??
23+
# - Number of primes less than is ??
24+
# - log7(800800^800800) < 5.6 x 10^6
25+
# - Largest prime less than is ??
26+
# - Number of primes less than is ??
27+
# - p^q * q^p = h
28+
# - log(p^q) + log(q^p) = log(h)
29+
# - q*log(p) + p*log(q) = log(h)
30+
# - Assume p = 2 and use log base q
31+
# - q*logq(2) + 2*1 = logq(h)
32+
# - q = 15999989
33+
# - 668574.6 =(?) logq(800800^800800) = 656227.6
34+
35+
import pytest
36+
import numpy
37+
import math
38+
from decimal import Decimal
39+
40+
# <https://stackoverflow.com/a/3035188>
41+
def primesfrom2to(n):
42+
""" Input n>=6, Returns a array of primes, 2 <= p < n """
43+
sieve = numpy.ones(n//3 + (n%6==2), dtype=bool)
44+
for i in range(1,int(n**0.5)//3+1):
45+
if sieve[i]:
46+
k=3*i+1|1
47+
sieve[ k*k//3 ::2*k] = False
48+
sieve[k*(k-2*(i&1)+4)//3::2*k] = False
49+
return numpy.r_[2,3,((3*numpy.nonzero(sieve)[0][1:]+1)|1)]
50+
51+
def test_can_get_primes():
52+
primes = primesfrom2to(16000000)
53+
assert len(primes) == 1031130
54+
assert 15999989 == primes[-1]
55+
56+
def C(n):
57+
largest_prime = math.ceil(log(n, 2))
58+
primes = primesfrom2to(largest_prime)
59+
numberOfPrimes = len(primes)
60+
print(numberOfPrimes)
61+
count = 0
62+
for i in range(numberOfPrimes):
63+
p = primes[i]
64+
nLog = log(n, p)
65+
count += max(binary_search(primes, nLog, lambda q: p * log(q, p) + q) - i, 0)
66+
if i % 100000 == 0:
67+
print(i)
68+
return count
69+
70+
def log(number, base):
71+
return math.log(number, base)
72+
73+
def binary_search(a, nLog, function):
74+
lo = 0
75+
hi = len(a)
76+
while lo < hi:
77+
mid = (lo+hi)//2
78+
midval = function(a[mid])
79+
if midval < nLog:
80+
lo = mid + 1
81+
elif midval > nLog:
82+
hi = mid
83+
else:
84+
return mid
85+
return hi - 1
86+
87+
@pytest.mark.skip(reason="48s to solve")
88+
def test_C_works_for_examples():
89+
"""You are given $C(800) = 2$ and $C(800^{800}) = 10790$."""
90+
# assert C(800) == 2
91+
# assert C(800**800) == 10790
92+
# assert C(8008**8008) == 440302
93+
# assert C(80080**8008) == 621290
94+
# assert C(80080**80080) == 23036066
95+
# assert C(800800**80080) == 31110609
96+
assert C(800800**800800) == 1412403576
97+

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ requires-python = "==3.12.*"
99
dev = [
1010
"pytest>=8.3.1",
1111
"pytest-timeout>=2.3.1",
12+
"numpy>=2.1.3",
1213
]
1314

1415
[tool.pdm.scripts]
15-
test = "pytest --timeout 20"
16+
test = "pytest --timeout 20 --durations=5"

0 commit comments

Comments
 (0)