Spiral Primes
Starting with 1 and spiralling anticlockwise, a square spiral with side length s is formed. The diagonals of this spiral contain certain values. What is the side length of the square spiral for whi...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Starting with \(1\) and spiralling anticlockwise in the following way, a square spiral with side length \(7\) is formed. \[ \begin {tabular}{ccccccc} \textcolor {red}{37} & 36 & 35 & 34 & 33 & 32 & \textcolor {red}{31} \\ 38 & \textcolor {red}{17} & 16 & 15 & 14 & \textcolor {red}{13} & 30 \\ 39 & 18 & \textcolor {red}{5} & 4 & \textcolor {red}{3} & 12 & 29 \\ 40 & 19 & 6 & 1 & 2 & 11 & 28 \\ 41 & 20 & \textcolor {red}{7} & 8 & 9 & 10 & 27 \\ 42 & 21 & 22 & 23 & 24 & 25 & 26 \\ \textcolor {red}{43} & 44 & 45 & 46 & 47 & 48 & 49 \\ \end {tabular} \] It is interesting to note that the odd squares lie along the bottom right diagonal, but what is more interesting is that \(8\) out of the \(13\) numbers lying along both diagonals are prime; that is, a ratio of \(8/13 \approx 62\%\).
If one complete new layer is wrapped around the spiral above, a square spiral with side length \(9\) will be formed. If this process is continued, what is the side length of the square spiral for which the ratio of primes along both diagonals first falls below \(10\%\)?
Problem 58: Spiral Primes
Mathematical Development
Definition 1 (Ulam Spiral Layers). The spiral is organized into layers indexed by , where layer is the center (containing only the value 1) and layer has side length .
Theorem 1 (Corner Values). For layer (side length ), the four diagonal corner values are:
Proof. The bottom-right corner of layer is the last number placed in that layer, namely . Moving counterclockwise along the outermost ring, consecutive corners are separated by positions. Thus, stepping back from :
Lemma 1 (Bottom-Right Corner is Always Composite). For , is composite.
Proof. has the nontrivial factor , so it is a perfect square greater than 1, hence composite.
Theorem 2 (Diagonal Element and Prime Counts). After processing layers through :
(i) The total number of diagonal elements is (including the center value 1).
(ii) The number of prime diagonal elements is
where is the indicator function. The fourth corner is excluded by Lemma 1.
Proof. (i) Layer 0 contributes 1 element. Each subsequent layer contributes 4 corners. After layers: . (ii) The center value 1 is not prime. At each layer , at most 3 of the 4 corners can be prime (since is always composite).
Theorem 3 (The Ratio ). The prime ratio along the diagonals tends to zero as .
Proof. The corner values at layer are . By the Prime Number Theorem, the probability that a random integer near is prime is asymptotically . For , this probability is .
The expected number of primes contributed by layer is therefore approximately , and
by the integral estimate (a consequence of the prime number theorem applied to the sum). The ratio is
Corollary 1 (Existence of Threshold Crossing). For any , there exists a finite such that . The problem asks for where .
Lemma 2 (Primality Testing Bound). To test whether is prime by trial division, it suffices to check divisors up to .
Proof. If is composite, it has a factor at most . Since , we have .
Proposition 1 (Rough Estimate via PNT). Setting gives , hence , corresponding to side length . This is a very rough lower bound; the actual answer is much larger because the PNT approximation overestimates the prime count for small to moderate .
Editorial
We process the spiral layer by layer. For each new side length , only the three non-square corner values need to be tested for primality, because the fourth corner is always and therefore composite. Maintaining the cumulative number of diagonal entries and diagonal primes allows the prime ratio to be updated after each layer, and the first side length for which this ratio falls below 10% is returned.
Pseudocode
Algorithm: Spiral Side Length at Which the Prime Ratio Falls Below One Tenth
Require: Primality testing for the diagonal corner values of the spiral.
Ensure: The first odd side length for which the ratio of prime numbers on the diagonals is less than 10%.
1: Initialize prime_count ← 0, diagonal_count ← 1, and k ← 0.
2: Repeat:
3: Set k ← k + 1 and s ← 2k + 1, then form the three non-square corner values on the layer of side length s.
4: Test those three corners for primality, update prime_count accordingly, and set diagonal_count ← diagonal_count + 4.
5: If prime_count / diagonal_count < 0.1, return s.
Complexity Analysis
Theorem 4 (Time Complexity). Let denote the final layer index (so ). With trial division, the algorithm runs in time. With Miller-Rabin primality testing, the time reduces to .
Proof. At each layer , we test 3 numbers for primality. Each corner value has . Trial division with the optimization tests candidates per number in the worst case, but the dominant cost across all layers is , since the trial division bound grows with .
With deterministic Miller-Rabin using a fixed set of witnesses, each primality test costs , giving total cost .
For the answer (side length ), , which is feasible.
Space: — only a constant number of integer variables are maintained.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// Modular multiplication using __int128 to avoid overflow.
ll mulmod(ll a, ll b, ll m) {
return (__int128)a * b % m;
}
// Fast modular exponentiation: base^exp mod mod.
ll powmod(ll base, ll exp, ll mod) {
ll result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = mulmod(result, base, mod);
base = mulmod(base, base, mod);
exp >>= 1;
}
return result;
}
// Single round of Miller-Rabin with witness a.
bool millerRabin(ll n, ll a) {
if (n % a == 0) return n == a;
ll d = n - 1;
int r = 0;
while (d % 2 == 0) { d /= 2; r++; }
ll x = powmod(a, d, n);
if (x == 1 || x == n - 1) return true;
for (int i = 0; i < r - 1; i++) {
x = mulmod(x, x, n);
if (x == n - 1) return true;
}
return false;
}
// Deterministic primality test for n < 3.2 * 10^18.
bool isPrime(ll n) {
if (n < 2) return false;
if (n < 4) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (ll a : {2, 3, 5, 7, 11, 13}) {
if (!millerRabin(n, a)) return false;
}
return true;
}
int main() {
int primeCount = 0;
int totalDiag = 1; // center = 1
for (ll k = 1; ; k++) {
ll s = 2 * k + 1;
ll sq = s * s;
totalDiag += 4;
// Three non-square corners: skip (2k+1)^2 by Lemma 1
if (isPrime(sq - (s - 1))) primeCount++;
if (isPrime(sq - 2 * (s - 1))) primeCount++;
if (isPrime(sq - 3 * (s - 1))) primeCount++;
if (primeCount > 0 && 10 * primeCount < totalDiag) {
cout << s << endl;
return 0;
}
}
return 0;
}
"""
Project Euler Problem 58: Spiral Primes
What is the side length of the square spiral for which the ratio
of primes along both diagonals first falls below 10%?
Corner values at layer k (side length s = 2k+1):
c1 = 4k^2 - 2k + 1, c2 = 4k^2 + 1, c3 = 4k^2 + 2k + 1
c4 = (2k+1)^2 (always composite, skipped)
Answer: 26241
"""
from sympy import isprime
def solve():
prime_count = 0
total_diag = 1 # center = 1
k = 0
while True:
k += 1
s = 2 * k + 1
sq = s * s
total_diag += 4
for corner in [sq - 2 * (s - 1), sq - (s - 1), sq - 3 * (s - 1)]:
if isprime(corner):
prime_count += 1
if prime_count > 0 and prime_count / total_diag < 0.10:
return s
if __name__ == "__main__":
answer = solve()
assert answer == 26241
print(answer)