Project Euler Problem 49 Solution

Project Euler Problem 49 Solution

Prime Permutations

by {BetaProjects} | Project Euler & HackerRank
Difficulty: Hard

Project Euler Problem 49 Statement

The arithmetic sequence, $1487, 4817, 8147$, in which each of the terms increases by $3330$, is unusual in two ways: (i) each of the three terms are prime, and, (ii) each of the $4$-digit numbers are permutations of one another.

There are no arithmetic sequences made up of three $1$-, $2$-, or $3$-digit primes, exhibiting this property, but there is one other $4$-digit increasing sequence.

What $12$-digit number do you form by concatenating the three terms in this sequence?

Solution

This script is designed to solve Project Euler Problem 49, which involves identifying prime numbers that are permutations of each other and form arithmetic sequences. The goal is to find sets of prime numbers that not only share the same digits but also exhibit a common difference between them, ultimately forming a sequence of length K.

This solution addresses the problem by finding sequences of primes that fulfill three main conditions:

  1. They are permutations (i.e. the primes contain the same digits in a different order).
  2. They form an arithmetic progression (i.e. the difference between consecutive primes is constant).
  3. The sequence contains a specified number of terms, represented by \(K\), with the first term less than \(N\).
1. Setup and Prime Generation

The code begins by importing necessary modules and reading the input:

from collections import defaultdict
import Euler

N, K = map(int, input().split())
p = Euler.prime_sieve(1_000_000)
2. Grouping Primes by Their Digit Permutations

To easily identify primes that are permutations of each other, each prime is converted to a canonical form. This is done by:

For example, the prime \(1487\) becomes \(\text{'1478'}\).

The following code snippet performs this grouping:

g = defaultdict(list)

for q in p:
    g[''.join(sorted(str(q)))].append(q)

Here, the primes are grouped in the dictionary g by their sorted digit strings.

3. Searching for Valid Arithmetic Sequences

The next step is to iterate through each group of primes (which are all permutations of each other) and search for arithmetic sequences.

res = []
for lst in g.values():
    for i in range(len(lst)):
        for j in range(i+1, len(lst)):
            d = lst[j] - lst[i]
            seq = [lst[i] + k*d for k in range(K)]
            if all(x in lst for x in seq) and lst[i] < N:
                res.append(''.join(map(str, seq)))
4. Sorting and Printing the Results

Finally, the found sequences are sorted and printed:

print("\n".join(sorted(res, key=lambda s: int(s[:len(s)//K]))))

HackerRank version

HackerRank Project Euler 49: You are given $N$, (2,000≤ N ≤ 1,000,000) and $K$, (3≤ K≤ 4) find all $K$ size sequences where first element is less than $N$, and $K$ elements are permutations of each other, are prime and are in Arithmetic Progression.

Python Source Code

from collections import defaultdict
import Euler
N, K = map(int, input().split())
p = Euler.prime_sieve(1_000_000)
g = defaultdict(list)

for q in p: g[''.join(sorted(str(q)))].append(q)
res = []
for lst in g.values():
    for i in range(len(lst)):
        for j in range(i+1, len(lst)):
            d = lst[j]-lst[i]
            seq = [lst[i]+k*d for k in range(K)]
            if all(x in lst for x in seq) and lst[i] < N:
                res.append(''.join(map(str, seq)))

print("\n".join(sorted(res, key=lambda s: int(s[:len(s)//K]))))	

Last Word