Skip to content

Commit 67babd3

Browse files
Add solution for Problem 810
1 parent 788d95b commit 67babd3

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

project_euler/problem_810/__init__.py

Whitespace-only changes.

project_euler/problem_810/sol1.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
"""
2+
Project Euler Problem 810: https://projecteuler.net/problem=810
3+
4+
We use x ⊕ y for the bitwise XOR of x and y.
5+
Define the XOR-product of x and y, denoted by x ⊗ y,
6+
similar to a long multiplication in base 2,
7+
except the intermediate results are XORed instead of usual integer addition.
8+
9+
For example, 7 ⊗ 3 = 9, or in base 2, 111_2 ⊗ 11_2 = 1001_2:
10+
111
11+
⊗ 11
12+
-------
13+
111
14+
111
15+
-------
16+
1001
17+
An XOR-Prime is an integer n greater than 1 that is not an
18+
XOR-product of two integers greater than 1.
19+
The above example shows that 9 is not an XOR-prime.
20+
Similarly, 5 = 3 ⊗ 3 is not an XOR-prime.
21+
The first few XOR-primes are 2, 3, 7, 11, 13, ... and the 10th XOR-prime is 41.
22+
23+
Find the 5,000,000.th XOR-prime.
24+
25+
References:
26+
http://en.wikipedia.org/wiki/M%C3%B6bius_function
27+
28+
"""
29+
30+
from bitarray import bitarray
31+
32+
33+
def xor_multiply(a: int, b: int) -> int:
34+
"""
35+
Perform XOR multiplication of two integers, equivalent to polynomial
36+
multiplication in GF(2).
37+
38+
>>> xor_multiply(3, 5) # (011) ⊗ (101)
39+
15
40+
"""
41+
res = 0
42+
while b:
43+
if b & 1:
44+
res ^= a
45+
a <<= 1
46+
b >>= 1
47+
return res
48+
49+
50+
def divisors(n: int) -> set[int]:
51+
"""
52+
Return all divisors of n (excluding 0).
53+
54+
>>> divisors(12)
55+
{1, 2, 3, 4, 6, 12}
56+
"""
57+
s = {1}
58+
for i in range(2, int(n**0.5) + 1):
59+
if n % i == 0:
60+
s.add(i)
61+
s.add(n // i)
62+
s.add(n)
63+
return s
64+
65+
66+
def mobius_table(n: int) -> list[int]:
67+
"""
68+
Generate Möbius function values from 1 to n.
69+
70+
>>> mobius_table(10)[:6]
71+
[0, 1, -1, -1, 0, -1]
72+
"""
73+
mob = [1] * (n + 1)
74+
is_prime = [True] * (n + 1)
75+
mob[0] = 0
76+
77+
for p in range(2, n + 1):
78+
if is_prime[p]:
79+
mob[p] = -1
80+
for j in range(2 * p, n + 1, p):
81+
is_prime[j] = False
82+
mob[j] *= -1
83+
p2 = p * p
84+
if p2 <= n:
85+
for j in range(p2, n + 1, p2):
86+
mob[j] = 0
87+
return mob
88+
89+
90+
def count_irreducibles(d: int) -> int:
91+
"""
92+
Count the number of irreducible polynomials of degree d over GF(2)
93+
using the Möbius function.
94+
95+
Args:
96+
d (int): Polynomial degree.
97+
98+
Returns:
99+
int: Count of irreducible polynomials.
100+
101+
Example:
102+
>>> count_irreducibles(3)
103+
2
104+
"""
105+
mob = mobius_table(d)
106+
total = 0
107+
for div in divisors(d) | {d}:
108+
total += mob[div] * (1 << (d // div))
109+
return total // d
110+
111+
112+
def find_xor_prime(rank: int) -> int:
113+
"""
114+
Find the Nth XOR prime using a bitarray-based sieve.
115+
116+
>>> find_xor_prime(10)
117+
41
118+
"""
119+
total, degree = 0, 1
120+
while True:
121+
count = count_irreducibles(degree)
122+
if total + count > rank:
123+
break
124+
total += count
125+
degree += 1
126+
127+
limit = 1 << (degree + 1)
128+
129+
sieve = bitarray(limit)
130+
sieve.setall(True)
131+
sieve[0:2] = False
132+
133+
for even in range(4, limit, 2):
134+
sieve[even] = False
135+
136+
current = 1
137+
for i in range(3, limit, 2):
138+
if sieve[i]:
139+
current += 1
140+
if current == rank:
141+
return i
142+
143+
j = i
144+
while True:
145+
prod = xor_multiply(i, j)
146+
if prod >= limit:
147+
break
148+
sieve[prod] = False
149+
j += 2
150+
151+
raise ValueError(
152+
"Failed to locate the requested XOR-prime within the computed limit"
153+
)
154+
155+
156+
def solution(limit: int = 5000001) -> int:
157+
"""
158+
Wrapper for Project Euler-style solution function.
159+
160+
>>> solution(10)
161+
41
162+
"""
163+
result = find_xor_prime(limit)
164+
return result
165+
166+
167+
if __name__ == "__main__":
168+
print(f"{solution(5000000) = }")

0 commit comments

Comments
 (0)