# Project Euler 58 Solution: Spiral primes

Problem 58

Starting with 1 and spiralling anticlockwise in the following way, a square spiral with side length 7 is formed.

37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18 5 4 3 12 29
40 19 6 1 2 11 28
41 20 7 8 9 10 27
42 21 22 23 24 25 26
43 44 45 46 47 48 49

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 ≈ 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%?

## Solution

With Problem 28 we found four equations to generate the diagonls of the matrix, even if it was clockwise and here anticlockwise. The pattern remains:

$\begin{array}{rll} a_n &= (9, 25, 49, 81, 121, ...) &= 4n^2 + 4n + 1\\ b_n &= (5, 17, 37, 65, 101, ...) &= 4n^2 + 1\\ c_n &= (3, 13, 31, 57, 91, ...) &= 4n^2 - 2n+1\\ d_n &= (7, 21,43, 73, 111, ...) &= 4n^2 + 2n + 1 \end{array}$

But instead of summing up, we use the generated diagonal numbers to count primes until the number of primes $$p$$ falls below 10%. This is $$\frac{p}{c}<0.1$$ for the total amount of diagonal numbers $$c$$. If we add all four new corners for every layer plus the starting element in the middle we have $$c=4n+1$$, which gives the break condition $$10p<4n+1$$.

The side length on layer $$n$$ is $$2n+1$$, which gives us the solution:

function solution() {

let p = 0;
for (let n = 1; ; n++) {
p+= isPrime(4 * n * n + 4 * n + 1);
p+= isPrime(4 * n * n + 1);
p+= isPrime(4 * n * n - 2 * n + 1);
p+= isPrime(4 * n * n + 2 * n + 1);
if (10 * p < 4 * n + 1) {
return 2 * n + 1;
}
}
}

We loop over odd numbers here. So, instead of looping over $$n$$, we now simplify the equations by looping over $$m=2n+1$$ and get a much prettier pattern:

$\begin{array}{rl}4n^2 + 4n + 1 &= m^2\\4n^2 + 2n + 1 &= (m - 1) m + 1\\4n^2 + 1 &= (m - 2) * m + 2\\4n^2 - 2n + 1 &= (m - 3) * m + 3\\\end{array}$

This result shows us that the bottom right corner always is a square and thus never prime. The new and faster solution with $$m$$ substituted is then

function solution() {

let p = 0;
for (let m = 3; ; m+= 2) {
p+= isPrime((m - 1) * m + 1);
p+= isPrime((m - 2) * m + 2);
p+= isPrime((m - 3) * m + 3);
if (10 * p < 2 * m - 1) {
return m;
}
}
}

The missing piece is a prime check, which we implemt straight away:

function isPrime(n) {
if (n <= 3) return n > 1;
if (n % 2 === 0 || n % 3 === 0) return false;

for (let i = 5; i * i <= n; i+= 6) {
if (n % i === 0 || n % (i+2) === 0)
return false;
}
return true;
}

« Back to problem overview
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 1, "mathjax_display_tex": 1, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.7755042314529419, "perplexity": 656.2262990390178}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2021-17/segments/1618038088471.40/warc/CC-MAIN-20210416012946-20210416042946-00071.warc.gz"}